Come determinare se un numero è pari o dispari senza operazioni mod o bit per bit? [chiuso]


19

Come determinare se un numero è pari o dispari senza operazioni mod o bit per bit?

Questa sfida è gravemente inefficiente, ma mette alla prova la tua capacità di pensare fuori dagli schemi per una soluzione creativa.

MODIFICA :

Si prega di creare una funzione. Inoltre, mentre regex è una risposta divertente, la funzione dovrebbe accettare qualsiasi numero valido.

BACKGROUND : Questa domanda nasce dai miei primi giorni di programmazione. I compiti per il nostro primo giorno di lezione consistevano nello scrivere un semplice programma che stampasse "dispari" o "pari". Essendo il marmocchio che ero, non ho letto il libro che avevamo per la classe in cui ci mostrava semplicemente come usarlo%per determinarlo. Ho passato circa mezz'ora a camminare avanti e indietro nella mia stanza cercando di pensare a un modo per farlo e ho ricordato dalla lezione che i numeri possono perdere e ottenere precisione mentre vengono lanciati da un tipo primitivo all'altro. Pertanto, se prendi il numero, lo dividi per due e poi lo moltiplichi indietro non equivale al numero originale, allora sapresti che il numero era dispari.

Rimasi sbalordito il giorno successivo, mentre il nostro istruttore stava valutando i nostri programmi, che pensava che fosse il modo più originale, anche se inefficiente, di risolvere il problema.


3
Dovremmo creare una funzione o un programma? Come dovrebbe accadere l'IO se dobbiamo fare un programma? Per favore, approfondisci ulteriormente.
Juan,

2
Quale criterio obiettivo determinerà la risposta accettata? Dimensione del codice? Qualcos'altro?
PleaseStand,

È sicuramente un numero? Dovrebbe dare falsi positivi per una stringa?
William,

Questo è in circolazione da molto tempo, ma non sembra esserci una condizione vincente di alcun tipo, il che a mio avviso significa che non c'è gioco qui.
dmckee,

Risposte:


40

Nella maggior parte dei linguaggi di programmazione la divisione restituisce un quoziente per numeri interi. Quindi puoi semplicemente controllare questo

(i/2)*2==i

6
Non necessariamente la maggior parte, direi. Molti, forse.
Joey,

1
per assicurarti che funzioni correttamente, devi assicurarti di lanciare tutto in un int/ longtipo
warren,

@warren Dipende dal linguaggio di programmazione / ottimizzazioni del compilatore / ecc. Inoltre, puoi usare floor(). Funziona perfettamente in C e C ++.
Mateen Ulhaq,

1
0 è un numero pari?
utente sconosciuto

4
@userunknown: Sì, zero è pari.
Keith Thompson,

71

Pitone

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

10
La semplice bellezza / bella semplicità della matematica ... molto bella!
jscs,

Mi piace molto questo.
Rob,

Lento ma creativo.
Mateen Ulhaq,

21

Brainf *** (179)

Questo è uno dei problemi più interessanti che coinvolgono la logica condizionale che ho fatto in BF.

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

Prende un input di testo con un numero. Se il numero è pari, viene emesso Ee, se è dispari, viene emesso O.

Ne sono abbastanza orgoglioso che mostrerò una forma più leggibile dall'uomo:

+[>,]                                                   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

matematica

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

2
Puoi dividere queste due soluzioni in risposte diverse?
FUZxxl,

Non sono queste quattro soluzioni?
Joey,

In realtà, tutti i nomi incorporati in Mathematica sono in maiuscolo, quindi per quanto possa sembrare divertente, dovresti usare Ie Piinvece di ie pi.
David Zhang,

15

C

Moltiplicato per se stesso alcune volte qualsiasi numero pari passerà a 0 dato un numero intero di dimensioni finite e qualsiasi numero dispari continuerà ad avere almeno il bit meno significativo impostato.

#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;
}

Modifica: come semplice funzione:

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

Assicurati di utilizzare numeri interi senza segno. L'overflow di numeri interi con segno è un comportamento indefinito in C, quindi l'ottimizzazione potrebbe fare qualcosa di strano se lo desiderasse.
Joey Adams,

13

Python (lento)

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

1
Funziona in modo positivo ... suppongo che potrei aggiungere una abs()chiamata all'inizio.
via

@Josh: Questo trucco è già apparso qui alcune volte :)
Joey,

Crediti a gnibblr :)
st0le

@Joey: non immaginavo che fosse nuovo, ma lo stile non deve essere originale. :)
jscs,

12

JavaScript

/[02468]$/.test(i)

rendimenti trueper un numero pari. Funziona solo con numeri interi di dimensioni ragionevoli (ad es. Non notazione scientifica quando convertito in una stringa e senza parte frazionaria).


2
Per soddisfare il requisito "funzione" è possibile modificarlo semplicemente /[02468]$/.test.
Ry,

Non era esattamente chiaro in questione, ma potrebbe essere possibile che l'ingresso non è un numero a tutti, /[02468]$/.test('I am a fake even number 0'). In tal caso, potresti farlo/^[0-9].[02468]$/.test(i)
William, il

/-?^\d*[02468]$/sarebbe un po 'più rigido del tuo regex. Avresti bisogno di più lavoro perché questo funzioni correttamente per i numeri che devono essere usati usando la notazione scientifica.
Thomas Eding,

12

Pitone

Dato che non sono davvero sicuro di quali siano i criteri di punteggio, ecco un sacco di soluzioni che ho escogitato per motivi di divertimento. Molti di loro usano abs(n)per supportare numeri negativi. La maggior parte, se non tutte, non dovrebbero mai essere utilizzate per calcoli reali.

Questo è un po 'noioso:

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"

E questo è il mio preferito anche se sfortunatamente non funziona (come sottolineato da March Ho di seguito: solo perché tutti i numeri pari sono la somma di due numeri primi, non significa che tutti i numeri dispari non lo siano).

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"

Soluzioni carine :-)
Joey,

2
Davvero un vecchio necro, ma la tua congettura di Goldbach non risponde nemmeno al 9? Sembra un caso di affermazione del conseguente errore
marzo Ho

Sì, hai assolutamente ragione al cento per cento, @MarchHo. Uovo sulla mia faccia.
jscs,

10

Haskell

Questa, ovviamente, non è in alcun modo la soluzione creativa e pensante fuori dagli schemi che stai cercando, ma quante volte riuscirò a pubblicare una risposta Haskell più corta di GolfScript, in realtà? È davvero un peccato che non sia un codice golf.

odd

Ma più seriamente:

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

sembra più lungo del risposta GolfScript
warren,

2
Mi riferivo al primo blocco ( odd) che è una funzione incorporata che restituisce True se il numero è dispari. Questa è una risposta completa da sola e più breve dell'attuale risposta GolfScript (che al momento della stesura di questo è 10 caratteri, ma mi aspetto che diminuisca). Anche la domanda è un po 'sotto specificata, motivo per cui asserisco che oddè sufficiente. Anche questo potrebbe cambiare.

1
ha perso la prima risposta nella tua risposta :)
warren,

1
Per lo meno l' parityalgoritmo funziona su tutte le Numistanze che sono numeri interi. Fa caldo! Anche se probabilmente l'avrei fatto evens = [0,2..] >>= \n -> [-n, n]. Simile per probabilità.
Thomas Eding

7

Usando una lettura deliberatamente perversa della domanda, "Come determinare se un numero è pari o dispari", ecco un'implementazione in C (ipotizza boole truesono definiti in modo appropriato):

bool is_odd_or_even(int n)
{
    return true;
}

La domanda menziona il numero, non il numero intero. Numero come 0.5restituisce truequando non dovrebbe.
Konrad Borowski,

6

Cosa, ancora nessun algoritmo randomizzato ??

C

#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]);
}

Associa casualmente numeri nell'intervallo 0 .. n -1 fino a quando rimangono meno di 2. E 'abbastanza incredibilmente inefficiente: O ( n 3 ).


Completamente differente:

Haskell

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

Usa il fatto che la trasformata di Fourier di una funzione pari (ad es. \x->x^^4) È reale, mentre la trasformata di Fourier di una funzione dispari è immaginaria.


5

Windows PowerShell

function OddOrEven([long]$n) {
  if (0,2,4,6,8 -contains "$n"[-1]-48) {
    "Even"
  } else {
    "Odd"
  }
}
  1. Converti in stringa
  2. Scegli l'ultima lettera (cifra) (essenzialmente una mod 10).
  3. Controlla se è 0, 2, 4, 6 o 8.

Nessun operatore bit a bit, nessun modulo, come richiesto.


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.

Per quanto ne so, questa è la prima voce coq su codegolf.

Ancora più corto (59):

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

4

Rubino

n.odd?

Se si desidera stampare il risultato:

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

Sto abbastanza usando ruby ​​usa mod nella .odd?definizione.
MrZander

4

Unlambda

Il mondo ha bisogno di più Unlambda.

Unlambda ha un vantaggio killer qui: la sua rappresentazione predefinita ( ahem ) per i numeri sono numeri di Church, quindi tutto ciò che serve è applicarli per funzionare binario, non per funzionare in modo vero. Facile!

PS: Markdown e Unlambda non sono fatti l'uno per l'altro.

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

Verifica per i primi numeri interi:

```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

Pitone

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

Prestazioni simili alla versione precedente. Funziona per 0 ora.

Versione precedente errata:

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

Non particolarmente efficiente; tempo e memoria ovviamente entrambi O (n): 32 msec per 1.000.000; 2,3 msec per 100000; 3.2 usec per 100. Funziona con numeri negativi. Genera un errore per 0, perché 0 non è né pari né dispari.


3
Zero è decisamente pari. Vedi anche: en.wikipedia.org/wiki/Parity_of_zero

@jloy: Aw, merda. Ho pensato che fosse "una caratteristica, non un bug". Altre revisioni ...
jscs,

3

Fractran

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

applicato a

63*2^abs(n)

produce 5se nè dispari o 1se nè pari.

Aggiornamento : molto più breve ma non così interessante:

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

è 2per dispari ne 1anche per n.


3

MMIX (4 byte)

Questo è un po 'barare. Non utilizzo né mod né bit manipolando le operazioni. È piuttosto che è integrato il test per i numeri pari / dispari. Supponendo che $3contenga il numero da testare e il risultato vada in $2:

ZSEV $2,$3,1

set $2per 1se $3è ancora e per 0se non. Mnemnoric ZSEVsignifica zero-set pari e ha la seguente semantica:

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

Per la riga sopra, mmixalgenera questi quattro byte di assembly:

7F 02 03 01

3

schema

Questa è la soluzione più inefficiente che io conosca.

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

3

Perl

Che dire

use Math::Trig;
print(cos(pi*@ARGV[0])>0?"even":"odd")

2

JavaScript, 36

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

Restituisce truese pari, in falsecaso contrario.



2

Pitone

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

testare il quadrato di i, quindi funziona anche con numeri negativi


2

F #

Ricorsione reciproca per la vittoria.

Un numero n è pari anche se è zero o (n-1) è dispari.

Un numero n è dispari se non è uguale a zero e (n-1) è pari.

(addominali aggiunti nel caso in cui qualcuno sia interessato alla parità di numeri negativi)

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


2

Cosa si qualifica come operazioni bit per bit? Sotto il cofano, è probabile che la divisione intera per 2 venga implementata come spostamento di bit.

Supponendo che i bit-shift non siano disponibili:

C / C ++

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

modifica Mancavano alcune parentesi e alla fine sono cambiate per rimuovere un turno e farlo fare di meno. Puoi testarlo con il seguente (in * 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

... anche se in Linux / tcsh, ho dovuto sfuggire alla barra rovesciata \n anche se era tra virgolette singole. Ho testato in little & big-endian, funziona correttamente in entrambi. Inoltre, l'ho copiato a mano; il computer con cui sto postando non ha un compilatore, quindi potrebbe avere degli errori.

x86 asm

            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

o

            shl  al, 7

o

            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

... seguito da:

            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

In alternativa, anche il turno e il confronto potrebbero essere fatti in questo modo:

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

A proposito, shle gli amici non sono
ammessi

2

Su un processore 68000 è possibile spostare un valore di parola dall'indirizzo definito dal valore da testare:

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

e lasciare che la trappola hardware per errore di indirizzo determini la natura pari / dispari del valore - se l'eccezione viene sollevata, il valore era dispari, altrimenti il ​​valore era pari:

 <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

Non funziona su CPU Intel x86 poiché sono più flessibili sull'accesso ai dati.


2

Pitone

Ho deciso di provare la soluzione più brutta e confusa a cui potevo pensare:

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]

Stampa e se pari, o se dispari.


2

Q

Continua a sottrarre 2 fino a x <2, quindi converti in bool

{1b$-[;2]/[2<=;abs x]}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.