Як визначити, чи число непарне або парне без модних або бітних операцій? [зачинено]


19

Як визначити, чи число непарне або парне без модних або бітних операцій?

Ця проблема є надзвичайно неефективною, але кидає виклик вашій здатності мислити нестандартно для творчого рішення.

Редагувати :

Створіть функцію. Крім того, хоча регулярний вираз є цікавою відповіддю, функція повинна приймати будь-яке дійсне число.

Передумови : Це питання виникає з моїх ранніх днів програмування. Домашнє завдання для нашого першого дня заняття полягало в тому, щоб написати просту програму, яка надрукувала «непарне» або «парне». Будучи братом, я не читав книгу, яку ми мали для класу, де вона просто показала нам, як це%можна визначити. Я провів близько півгодини, крокуючи вперед у своїй кімнаті, намагаючись придумати спосіб зробити це, і згадав з лекції, що цифри можуть втратити і набути точності, коли вони передаються від одного примітивного типу до іншого. Тому, якщо ви взяли число, розділили його на два і потім помножили назад, не було рівним початковому числу, то ви б знали, що це число непарне.

Я був приголомшений наступного дня, поки наш інструктор оцінював наші програми, він вважав, що це найоригінальніший, якщо неефективний спосіб вирішення проблеми.


3
Чи слід створити функцію чи програму? Як має відбутися IO, якщо нам доведеться робити програму? Будь ласка, докладніше.
Хуан

2
Який об’єктивний критерій визначатиме прийняту відповідь? Розмір коду? Щось ще?
Будь ласка, продовжте

Це однозначно число? Чи повинен він давати помилкові позитиви для рядка?
Вільям

Це існує вже досить давно, але, здається, немає переможних умов такого роду, що, на мій погляд, означає, що тут немає гри.
dmckee

Відповіді:


40

У більшості мов програмування поділ повертає коефіцієнт для цілих чисел. Тож ви можете просто перевірити це

(i/2)*2==i

6
Не обов'язково більшість, я б сказав. Багато, можливо.
Джої

1
щоб переконатися, що він працює належним чином, вам потрібно переконатися, що ви передали все в int/ longtype
warren

@warren Залежить від мови програмування / оптимізації компілятора / тощо. Додатково можна використовувати floor(). Це чудово працює в C і C ++.
Mateen Ulhaq

1
Чи 0 - парне число?
користувач невідомий

4
@userunknown: Так, нуль є парним.
Кіт Томпсон

71

Пітон

print('even' if (-1)**n==1 else 'odd')

10
Проста краса / красива простота математики ... дуже приємно!
jscs

Мені це дуже подобається.
Роб

Повільний, але креативний.
Mateen Ulhaq

21

Brainf *** (179)

Це одна з найцікавіших проблем, пов’язана з умовною логікою, яку я зробив у BF.

+[>,]<--------------------------------------->>+++++[>+++++++
++++++>+++++++++++++++<<-]>++++>++++<<+<+<-[>-<-[>+<-[>-<-[>+<-[>-<-[>
+<-[>-<-[>+<-[>-<[-]]]]]]]]]]>[>>>.<<-<-]>[>.<-]

Він займає введення тексту з цифрою. Якщо число парне, воно виводить E, а якщо воно непарне - виводить O.

Я досить пишаюсь тим, що покажу більш зрозумілу людину форму:

+[>,]                                                   steps through input until it reaches eof.
<---------------------------------------                gets the numerical value of the last digit
>>+++++[>+++++++++++++>+++++++++++++++<<-]>++++>++++    store E and O
<<+<+<                                                  store a bit indicating parity, and a temporary bit
-[>-<                                                   !1
  -[>+<                                                 && !2
    -[>-<                                               && !3
      -[>+<                                             && !4
        -[>-<                                           && !5
          -[>+<                                         && !6
            -[>-<                                       && !7
              -[>+<                                     && !8
                -[>-<[-]]                               && !9
              ]
            ]
          ]
        ]
      ]
    ]
  ]
]
>[>>>.<<-<-]>[>.<-]                                     Display E or O based on the value of the parity bit.

21

Математика

SawtoothWave[x / 2] == 0
Exp[I Pi x] - 1 == 0
Sin[5 x / Pi] == 0

2
Чи можете ви розділити ці два рішення на різні відповіді?
FUZxxl

Чи не ці чотири рішення?
Джої

Насправді всі вбудовані імена в Mathematica з великої літери, настільки ж смішні, як це виглядає, слід використовувати Iі Piзамість, iі pi.
Девід Чжан

15

С

Помножене на себе кілька разів будь-яке парне число переповниться на 0 із заданим цілим числом кінцевого розміру, і будь-яке непарне число продовжить мати принаймні найменший значущий біт.

#include "stdio.h"
long long input=123;
int main(){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    if(input){
        printf("Odd");
    }
    else{
        printf("Even");
    }
    return 0;
}

Правка: як проста функція:

int isOdd(long long input){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    return !!input;
}

Обов’язково використовуйте непідписані цілі числа. Переповнення підписаних цілих чисел є невизначеною поведінкою в С, тому оптимізація може зробити щось дивне, якби воно хотіло.
Joey Adams

13

Пітон (повільно)

n=1234
while n > 1: n -= 2 #slow way of modulus.
print "eovdedn"[n::2]

1
Працює позитивно ... Я гадаю, що я міг би додати abs()дзвінок на початку.
st0le

@Josh: Цей трюк з’явився тут уже кілька разів :)
Joey

Кредити gnibblr :)
st0le

@Joey: Я не вважав, що це новий, але стиль не повинен бути оригінальним. :)
jscs

12

JavaScript

/[02468]$/.test(i)

врожайність trueдля парного числа. Це працює лише з цілими числами досить розміру (наприклад, не наукові позначення при перетворенні на рядок і не мають дробової частини.)


2
Щоб відповідати вимозі "функції", ви можете змінити її просто /[02468]$/.test.
Ри-

Це було не зовсім ясно , в цьому питанні , але це може бути можливо , що вхід не є числом взагалі /[02468]$/.test('I am a fake even number 0'). У такому випадку ви могли б зробити/^[0-9].[02468]$/.test(i)
Вільям

/-?^\d*[02468]$/було б трохи суворіше, ніж ваш регекс. Для цього вам знадобиться більше роботи, щоб нормально працювати для чисел, які будуть накреслені за допомогою наукових позначень.
Томас Едінг

12

Пітон

Оскільки я не дуже впевнений, якими є критерії оцінювання балів, ось я розробив купу рішень заради розваг. Більшість із них використовують abs(n)для підтримки негативних чисел. Більшість, якщо не всі, їх ніколи не слід використовувати для реального розрахунку.

Цей вид нудний:

from __future__ import division
def parity(n):
    """An even number is divisible by 2 without remainder."""
    return "Even" if n/2 == int(n/2) else "Odd"

def parity(n):
    """In base-10, an odd number's last digit is one of 1, 3, 5, 7, 9."""
    return "Odd" if str(n)[-1] in ('1', '3', '5', '7', '9') else "Even"

def parity(n):
    """An even number can be expressed as the sum of an integer with itself.

    Grossly, even absurdly inefficient.

    """
    n = abs(n)
    for i in range(n):
        if i + i == n:
            return "Even"
    return "Odd"

def parity(n):
    """An even number can be split into two equal groups."
    g1 = []
    g2 = []
    for i in range(abs(n)):
        g1.append(None) if len(g1) == len(g2) else g2.append(None)
    return "Even" if len(g1) == len(g2) else "Odd"

import ent # Download from: http://wstein.org/ent/ent_py
def parity(n):
    """An even number has 2 as a factor."""
    # This also uses modulo indirectly
    return "Even" if ent.factor(n)[0][0] == 2 else "Odd"

І це моє улюблене, хоча воно, на жаль, не спрацьовує (на що вказував Март Хо нижче: тільки тому, що всі парні числа є сумою двох простих чисел, не означає, що всі непарні числа не є).

import itertools
import ent    # Download from: http://wstein.org/ent/ent_py
def parity(n)
    """Assume Goldbach's Conjecture: all even numbers greater than 2 can
    be expressed as the sum of two primes.

    Not guaranteed to be efficient, or even succeed, for large n.

    """
    # A few quick checks
    if n in (-2, 0, 2): return "Even"
    elif n in (-1, 1): return "Odd"
    if n < 0: n = -n    # a bit faster than abs(n)
    # The primes generator uses the Sieve of Eratosthenes
    # and thus modulo, so this is a little bit cheating
    primes_to_n = ent.primes(n)
    # Still one more easy way out
    if primes_to_n[-1] == n: return "Odd"
    # Brutish!
    elif n in (p1+p2 for (p1, p2) in itertools.product(primes_to_n, primes_to_n)):
        return "Even"
    else:
        return "Odd"

Симпатичні рішення :-)
Joey

2
Дійсно старий некролог, але чи не друкується відповідь вашої гільдбаха навіть на 9? Схоже на випадок підтвердження наслідків помилок
Березень Хо

Так, ви абсолютно стовідсотково праві, @MarchHo. Яйце на моєму обличчі.
jscs

10

Хаскелл

Це, звичайно, ніяк не креативне, роздумливе поза межами коробки рішення, яке ви шукаєте, але скільки разів я збираюся потрапити, щоб опублікувати відповідь Haskell коротше, ніж GolfScript, насправді? Це справді прикро, що це не гольф з кодом.

odd

Але більш серйозно:

data Parity = Even | Odd
            deriving (Show)

parity = p evens odds
  where p (x:xs) (y:ys) i | i == x = Even
                          | i == y = Odd
                          | otherwise = p xs ys i
        evens = interleave [0,2..] [-2,-4..]
        odds = interleave [1,3..] [-1,-3..]
        interleave (x:xs) ys = x : interleave ys xs

виглядає довше, ніж відповідь GolfScript для мене
warren

2
Я мав на увазі перший блок ( odd), який є вбудованою функцією, яка повертає True, якщо число непарне. Це повна відповідь сама по собі і коротша, ніж нинішня відповідь GolfScript (що на момент написання цього становить 10 знаків, але я очікую, що це зменшиться). Питання також трохи не вказане, тому я стверджую, що oddцього достатньо. Це також може змінитися.

1
пропустив першу відповідь у своїй відповіді :)
warren

1
Як мінімум, parityалгоритм працює на всіх Numцілих числах. Це гаряче! Хоча я, мабуть, зробив би це evens = [0,2..] >>= \n -> [-n, n]. Подібні для шансів.
Thomas Eding

7

Використовуючи свідомо перекручене читання питання "Як визначити, чи число непарне чи парне", ось реалізація C (припустимо boolта trueвизначено належним чином):

bool is_odd_or_even(int n)
{
    return true;
}

У питанні зазначається число, а не ціле число. Число, як 0.5повертається, trueколи не повинно.
Конрад Боровський

6

Що, ще немає рандомізованих алгоритмів ??

С

#include<stdio.h>
#include<stdlib.h>

void prt_parity_of(int n){
  int i,j=2;
  char o[]="eovdedn"
     , f[n=abs(n)]; for(i=n;i-->0;f[i]=1);

  while(j>1){
    while((i=rand()%n)
       == (j=rand()%n)
       || (f[i]&f[j]>0)
       && (f[i]=f[j]=0)
    );for(i=j=0; ++i<n; j+=f[i])
  ;}for(;j<7;j+=2)putchar(o[j]);
}

Довільно парні числа в діапазоні 0 .. n -1, поки не залишиться менше 2. Це досить дивно неефективно: O ( п 3 ).


Зовсім інші:

Хаскелл

import Data.Complex

ft f = (\ω -> sum[ f(t) * exp(0:+2*pi*ω*t) | t<-[-1,-0.9..1] ] )

data Parity = Even | Odd deriving (Show)

parity n
  | all (\(re:+im) -> abs re > abs im) [ft ((:+0).(^^n)) ω | ω<-[0..20]]  = Even
  | otherwise                                                             = Odd

Використовує той факт, що перетворення Фур'є парної функції (наприклад \x->x^^4) є реальним, тоді як перетворення Фур'є непарної функції є уявним.


5

Windows PowerShell

function OddOrEven([long]$n) {
  if (0,2,4,6,8 -contains "$n"[-1]-48) {
    "Even"
  } else {
    "Odd"
  }
}
  1. Перетворити в рядок
  2. Виберіть останню букву (цифру) (по суті, мод 10).
  3. Перевірте, чи це 0, 2, 4, 6 або 8.

Ні бітових операторів, ні модулів, як вимагається.


5

Coq, 103

Fixpoint even n:=match n with O=>true|S n=>odd n end with odd n:=match n with O=>false|S n=>even n end.

Наскільки я можу сказати, це перший запис кок на кодогольфі.

Ще коротше (59):

Fixpoint even n:=match n with O=>true|S n=>negb(even n)end.

4

Рубін

n.odd?

Якщо ви хочете роздрукувати результат:

f[n] = ->(n){puts n.odd?? 'odd' : 'even'}

Я справедливо використовую модні рубінові використання у .odd?визначенні.
MrZander

4

Unlambda

Світ потребує більше Unlambda.

У Unlambda тут є перевага вбивці: його дефолт ( ах ) представлення чисел - церковні цифри, тому все, що потрібно, це застосувати їх для функцій бінарного, а не для функціонування істинного. Легко!

PS: Markdown і Unlambda, безумовно, не створені один для одного.

true  = i
false = `ki
not   = ``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki
even? = ``s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki

Перевірка для перших кількох цілих чисел:

```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki`ki                   => i
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`kii                     => `ki
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki``s``s`kski           => i
```s``si`k``s``s``s`k``s``si`k`kk`k`kii`k`ki`ki`ki``s``s`ksk``s``s`kski =>`ki


3

Пітон

print (["even"] + (["odd", "even"] * abs(n)))[abs(n)]

Аналогічні показники як у попередній версії. Зараз працює 0.

Неправильна більш рання версія:

print ((["odd", "even"] * abs(n))[:abs(n)])[-1]

Не особливо ефективний; час і пам'ять, очевидно, O (n): 32 мсек на 1 000 000; 2,3 мсек на 100000; 3.2 Usec для 100. Працює з від’ємними числами. Припускає помилку за 0, оскільки 0 не є парним і незвичайним.


3
Нуль, безумовно, рівний. Дивіться також: en.wikipedia.org/wiki/Pality_of_zero

@jloy: Ой, лайно. Я думав, що це "особливість, а не помилка". Більше ревізій ...
jscs

3

Фрактран

[65/42,7/13,1/21,17/7,57/85,17/19,7/17,1/3]

застосовується до

63*2^abs(n)

врожайність або 5якщо nнепарна, або 1якщо nпарна.

Оновлення : набагато коротше, але не так цікаво:

[1/4](2^abs(n))

є 2для непарних nі 1парних n.


3

MMIX (4 байти)

Це свого роду обман. Я не використовую ні операцій мод, ні біт. Це швидше тестування непарних / парних чисел. Припустимо, що $3містить число для тестування, і результат переходить у $2:

ZSEV $2,$3,1

набори $2до , 1якщо $3навіть і в іншому 0випадку. Мнеморіка ZSEVозначає нульовий набір і має таку семантику:

ZSEV a,b,c: if (even b) a = c; else a = 0;

Для вищевказаного рядка mmixalгенерує ці чотири байти складання:

7F 02 03 01

3

Схема

Це найефективніше рішення, про яке я знаю.

(letrec ([even? (lambda (n)
                 (if (zero? n) "even"
                     (odd? (- n 2))))]
         [odd? (lambda (n)
                 (if (= n 1) "odd"
                     (even? (- n 2))))])
  (even? (read)))


2

JavaScript, 36

function(i){while(i>0)i-=2;return!i}

Повертається, trueякщо навіть, falseякщо ні.



2

Пітон

zip((False, True)*(i*i), range(i*i))[-1][0]

тестуючи квадрат i, тож він працює і для від’ємних чисел


2

F #

Взаємна рекурсія на виграш.

Число n є навіть, якщо воно дорівнює нулю або (n-1) непарне.

Число n непарне, якщо воно нерівне нулю і (n-1) парне.

(abs додається у випадку, якщо когось цікавить парність негативних чисел)

let rec even n = n = 0 || odd (abs n - 1) 
    and odd n = n <> 0 && even (abs n - 1)


2

Що кваліфікується як бітові операції? Під кришкою, ціле ділення на 2, ймовірно, буде реалізовано як бітове зсув.

Припустимо, що бітзміни не виходять:

C / C ++

(unsigned char)((unsigned char)(n > 0 ? n : -n) << 7) > 0 ? "odd" : "even"

редагувати пропущені деякі круглі дужки, і в кінцевому рахунку змінити, щоб видалити зсув, щоб зробити його менше. Ви можете перевірити це за допомогою наступного (у * nix):

echo 'main(){ std::cout<< (unsigned char)((unsigned char)(n > 0 ? n : -n) << 7) > 0 \
        ? "odd\n" : "even\n";}' \
  | gcc --include iostream -x c++ -o blah -
./blah

... хоча в Linux / tcsh мені довелося уникати зворотної косої риски \n хоча це було в одноцитатах Я тестував у little & big-endian, він працює правильно в обох. Також я це скопіював вручну; на комп’ютері, з яким я розміщую повідомлення, немає компілятора, тому він може мати помилки.

x86 асм

            mov eax, n          # Get the value
            cmp eax,0           # Is it zero?
            jge pos_label       # If >= 0, skip the next part
            neg eax
pos_label:

.

            imul al, 128

або

            shl  al, 7

або

            lea  eax, [eax*8]    # Multiply by 2^3 (left-shift by 3 bits)
            lea  eax, [eax*8]    # ... now it's n*2^6
            lea  eax, [eax*2]    # ... 2^7, or left-shift by 7 bits

... далі:

            cmp al,  0          # Check whether the low byte in the low word is zero or not
            jz  even_label      # If it's zero, then it was an even number
            odd_label           # ... otherwise it wasn't

Крім того, зміщення та порівняння матеріалів може бути зроблено і таким чином:

            sar al,1            # signed integer division by 2 on least-significant byte
            jc  odd_label       # jump if carry flag is set

До речі, shlі друзів заборонено ...
FUZxxl

2

На процесорі 68000 ви можете перемістити значення слова з адреси, визначеної значенням для тестування:

 move.l <number to test>,a0
 move.w (a0),d0
 ; it's even if the next instruction is executed

і дозвольте апаратній пастці для помилки адреси визначити непарний / парний характер значення - якщо виняток підвищено, значення було непарним, якщо ні, значення було парним:

 <set up address error trap handler>
 move.l <pointer to even string>,d1
 move.l <number to test>,a0
 move.w (a0),d0
 <reset address error trap handler>
 <print string at d1>
 <end>

 address_error_trap_handler:
 move.l <pointer to odd string>,d1
 rte

Не працює на процесорах Intel x86, оскільки вони є більш гнучкими щодо доступу до даних.


2

Пітон

Я вирішив спробувати найгидніше, найгуканіше рішення, про яке я міг придумати:

n=input();r=range(n+1)
print [j for i in zip(map(lambda x:str(bool(x))[4],[8&7for i in r]),
map(lambda x:str(x)[1],[[].sort()for x in r])) for j in i][n]

Друкує е, якщо парне, o, якщо непарне.


2

Q

Продовжуйте віднімати 2, поки х <2, а потім перетворите на bool

{1b$-[;2]/[2<=;abs x]}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.