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


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.