Wie kann man feststellen, ob eine Zahl ungerade oder gerade ist, ohne mod- oder bitweise Operationen? [geschlossen]

19

Wie kann man feststellen, ob eine Zahl ungerade oder gerade ist, ohne mod- oder bitweise Operationen?

Diese Herausforderung ist äußerst ineffizient, fordert jedoch Ihre Fähigkeit heraus, über den Tellerrand hinauszudenken, um eine kreative Lösung zu finden.

EDIT :

Bitte erstellen Sie eine Funktion. Auch wenn Regex eine unterhaltsame Antwort ist, sollte die Funktion jede gültige Zahl akzeptieren .

HINTERGRUND : Diese Frage stammt aus meinen frühesten Programmiertagen. Die Hausaufgabe für unseren ersten Unterrichtstag bestand darin, ein einfaches Programm zu schreiben, das "ungerade" oder "gerade" druckte. Da ich der Balg war, habe ich das Buch, das wir für die Klasse hatten, nicht gelesen. Es zeigte uns einfach, wie man%das bestimmt. Ich verbrachte ungefähr eine halbe Stunde damit, in meinem Zimmer auf und ab zu gehen, und hatte in der Vorlesung daran gedacht, dass Zahlen an Präzision verlieren und zunehmen können, wenn sie von einem primitiven Typ zum nächsten gewechselt werden. Wenn Sie also die Zahl nehmen, durch zwei teilen und dann zurückmultiplizieren, entspricht dies nicht der ursprünglichen Zahl, und Sie würden wissen, dass die Zahl ungerade ist.

Ich war am nächsten Tag fassungslos, als unser Ausbilder unsere Programme evaluierte. Er fand, dass dies die originellste, wenn auch ineffizienteste Art war, das Problem zu lösen.

Wayne Hartman
quelle
3
Sollen wir eine Funktion oder ein Programm erstellen? Wie soll IO passieren, wenn wir ein Programm machen müssen? Bitte arbeiten Sie weiter aus.
Juan
2
Welches objektive Kriterium bestimmt die akzeptierte Antwort? Codegröße? Etwas anderes?
PleaseStand
Ist es definitiv eine Zahl? Sollte es für eine Zeichenfolge falsch positive Ergebnisse geben?
William
Das gibt es schon eine ganze Weile, aber es scheint keine Gewinnbedingung zu geben, was meiner Meinung nach bedeutet, dass es hier kein Spiel gibt.
dmckee

Antworten:

40

In den meisten Programmiersprachen gibt die Division den Quotienten für ganze Zahlen zurück. Sie können dies also einfach überprüfen

(i/2)*2==i
fR0DDY
quelle
6
Nicht unbedingt die meisten, würde ich sagen. Viele vielleicht.
Joey
1
es läuft richtig zu gewährleisten, müssen Sie sicherstellen, dass Sie alles in eine Guss int/ longTyp
warren
@warren Abhängig von der Programmiersprache / Compileroptimierungen / etc. Darüber hinaus können Sie verwenden floor(). Das funktioniert perfekt in C und C ++.
Mateen Ulhaq
1
Ist 0 eine gerade Zahl?
Benutzer unbekannt
4
@userunknown: Ja, null ist gerade.
Keith Thompson
71

Python

print('even' if (-1)**n==1 else 'odd')
dan04
quelle
10
Die einfache Schönheit / schöne Einfachheit der Mathematik ... sehr schön!
jscs
Ich mag dieses sehr.
Rob
Langsam aber kreativ.
Mateen Ulhaq
21

Brainf *** (179)

Dies ist eines der interessanteren Probleme mit der bedingten Logik, die ich in BF gemacht habe.

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

Es dauert eine Texteingabe mit einer Nummer. Wenn die Zahl gerade ist, wird sie ausgegeben E, und wenn sie ungerade ist, wird sie ausgegeben O.

Ich bin stolz genug darauf, dass ich eine besser lesbare Form zeigen werde:

+[>,]                                                   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.
Peter Olson
quelle
21

Mathematica

SawtoothWave[x / 2] == 0
Exp[I Pi x] - 1 == 0
Sin[5 x / Pi] == 0
Ming-Tang
quelle
2
Können Sie diese beiden Lösungen in verschiedene Antworten aufteilen?
FUZxxl
Sind das nicht vier Lösungen?
Joey
Tatsächlich werden alle in Mathematica eingebauten Namen in Großbuchstaben geschrieben. So lustig es auch aussieht, Sie sollten Iund Pianstelle von iund verwenden pi.
David Zhang
15

C

Wird eine gerade Zahl ein paar Mal für sich multipliziert, läuft sie bei einer Ganzzahl mit endlicher Größe auf 0 über, und für eine ungerade Zahl wird weiterhin mindestens das niedrigstwertige Bit gesetzt.

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

Edit: Als einfache Funktion:

int isOdd(long long input){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    return !!input;
}
aaaaaaaaaaa
quelle
Achten Sie darauf, vorzeichenlose ganze Zahlen zu verwenden. Der Überlauf von Ganzzahlen mit Vorzeichen ist in C undefiniertes Verhalten, daher könnte die Optimierung etwas Seltsames bewirken, wenn dies gewünscht wird.
Joey Adams
13

Python (langsam)

n=1234
while n > 1: n -= 2 #slow way of modulus.
print "eovdedn"[n::2]
st0le
quelle
1
Funktioniert für positive ... Ich nehme an, ich könnte abs()am Anfang einen Anruf hinzufügen .
st0le
@Josh: Dieser Trick ist hier schon einige Male aufgetaucht :)
Joey
Dank an gnibblr :)
st0le
@ Joey: Ich habe nicht gedacht, dass es neu ist, aber Stil muss nicht originell sein. :)
jscs
12

JavaScript

/[02468]$/.test(i)

ergibt trueeine gerade Zahl. Dies funktioniert nur mit Ganzzahlen von angemessener Größe (z. B. keine wissenschaftliche Notation, wenn sie in eine Zeichenfolge konvertiert wurde und keinen Bruchteil enthält).

PleaseStand
quelle
2
Um die "Funktions" -Anforderung zu erfüllen, können Sie sie einfach ändern /[02468]$/.test.
Ry
Es war in der Frage nicht genau klar, aber es könnte möglich sein, dass die Eingabe überhaupt keine Zahl ist /[02468]$/.test('I am a fake even number 0'). In diesem Fall könnten Sie tun/^[0-9].[02468]$/.test(i)
William
/-?^\d*[02468]$/wäre etwas strenger als dein regulärer Ausdruck. Sie würden mehr Arbeit benötigen, damit dies für Zahlen, die in wissenschaftlicher Notation eingegeben werden, richtig funktioniert.
Thomas Eding
12

Python

Da ich mir nicht sicher bin, was die Bewertungskriterien sind, sind hier einige Lösungen, die ich mir zum Vergnügen ausgedacht habe. Die meisten von ihnen abs(n)unterstützen negative Zahlen. Die meisten, wenn nicht alle, sollten niemals für echte Berechnungen verwendet werden.

Dieser ist irgendwie langweilig:

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"

Und dies ist mein Favorit, obwohl es leider nicht funktioniert (wie von March Ho unten ausgeführt: Nur weil alle geraden Zahlen die Summe von zwei Primzahlen sind, heißt das nicht, dass nicht alle ungeraden Zahlen sind).

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"
jscs
quelle
Nette Lösungen :-)
Joey
2
Wirklich ein alter Nekro, aber antwortet Ihre Goldbach-Vermutung nicht auch auf 9? Scheint, als würde man den daraus resultierenden Irrtum bekräftigen
March Ho
Ja, Sie haben absolut hundertprozentig Recht, @MarchHo. Ei auf meinem Gesicht.
jscs
10

Haskell

Dies ist natürlich keineswegs die kreative Lösung, nach der Sie über den Tellerrand schauen, aber wie oft werde ich tatsächlich eine Haskell-Antwort veröffentlichen, die kürzer als GolfScript ist? Es ist wirklich eine Schande, dass dies kein Code-Golf ist.

odd

Aber im Ernst:

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

quelle
mehr sieht als die GolfScript Antwort auf mich
warren
2
Ich bezog mich auf den ersten Block ( odd), der eine eingebaute Funktion ist, die True zurückgibt, wenn die Zahl ungerade ist. Das ist eine vollständige Antwort für sich und kürzer als die aktuelle GolfScript-Antwort (die zum Zeitpunkt des Schreibens 10 Zeichen beträgt, aber ich gehe davon aus, dass sie sinken wird). Die Frage ist auch ein bisschen unterbestimmt, weshalb ich das oddfür ausreichend halte . Das kann sich auch ändern.
1
habe die erste Antwort in deiner Antwort verpasst :)
warren
1
Zumindest parityfunktioniert der Algorithmus auf allen NumInstanzen, die Ganzzahlen sind. Das ist heiß! Obwohl ich es wahrscheinlich getan hätte evens = [0,2..] >>= \n -> [-n, n]. Ähnliches gilt für Quoten.
Thomas Eding
7

Anhand einer absichtlich perversen Lesart der Frage "Wie kann man feststellen, ob eine Zahl gerade oder ungerade ist?" Folgt eine C-Implementierung (vorausgesetzt boolund trueentsprechend definiert):

bool is_odd_or_even(int n)
{
    return true;
}
Keith Thompson
quelle
Die Frage nennt die Zahl, nicht die ganze Zahl. Zahl wie 0.5kehrt zurück, truewenn es nicht sollte.
Konrad Borowski
6

Was, noch keine randomisierten Algorithmen?

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

Zahlen im Bereich von 0 .. n -1 werden zufällig gepaart, bis weniger als 2 übrig sind. Es ist ganz erstaunlich ineffizient: O ( n 3 ).


Völlig anders:

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

Verwendet die Tatsache, dass die Fouriertransformation einer geraden Funktion (zB \x->x^^4) real ist, während die Fouriertransformation einer ungeraden Funktion imaginär ist.

hörte auf, sich gegen den Uhrzeigersinn zu drehen
quelle
5

Windows PowerShell

function OddOrEven([long]$n) {
  if (0,2,4,6,8 -contains "$n"[-1]-48) {
    "Even"
  } else {
    "Odd"
  }
}
  1. In Zeichenfolge konvertieren
  2. Wähle den letzten Buchstaben (Ziffer) (im Wesentlichen ein Mod 10).
  3. Überprüfen Sie, ob es 0, 2, 4, 6 oder 8 ist.

Keine bitweisen Operatoren, kein Modul, wie gewünscht.

Joey
quelle
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.

Soweit ich weiß, ist dies der erste CoQ-Eintrag zu Codegolf.

Noch kürzer (59):

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

Rubin

n.odd?

Wenn Sie das Ergebnis ausdrucken möchten:

f[n] = ->(n){puts n.odd?? 'odd' : 'even'}
Lowjacker
quelle
Ich benutze ziemlich ruby ​​benutze mod in der .odd?definition.
MrZander
4

Unlambda

Die Welt braucht mehr Unlambda.

Unlambda hat hier einen Killer-Vorteil: Die Standarddarstellung ( Ahem ) für Zahlen sind kirchliche Zahlen. Alles, was Sie also brauchen, ist, sie auf die Funktion binary anzuwenden - nicht auf true. Einfach!

PS: Markdown und Unlambda sind definitiv nicht aufeinander abgestimmt.

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

Überprüfung für die ersten ganzen Zahlen:

```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
JB
quelle
3

Golfscript

~,2/),1=\;
SIE
quelle
3

Python

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

Ähnliche Leistung wie die frühere Version. Funktioniert jetzt für 0.

Inkorrekte frühere Version:

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

Nicht besonders effizient; Zeit und Gedächtnis beide offensichtlich O (n): 32 ms für 1.000.000; 2,3 ms für 100000; 3,2 usec für 100. Funktioniert mit negativen Zahlen. Wirft einen Fehler für 0, da 0 weder gerade noch ungerade ist.

jscs
quelle
3
Null ist definitiv gerade. Siehe auch: en.wikipedia.org/wiki/Parity_of_zero
@jloy: Oh, Mist. Ich dachte, das sei "ein Feature, kein Bug". Weitere Überarbeitungen ...
jscs
3

Fractran

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

angewendet

63*2^abs(n)

ergibt entweder 5wenn nungerade oder 1wenn gerade nist.

Update : Viel kürzer aber nicht so interessant:

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

ist 2für ungerade nund 1für gerade n.

Howard
quelle
3

MMIX (4 Bytes)

Das ist eine Art Betrug. Ich benutze weder Mod- noch Bit-Fiddling-Operationen. Es ist eher so, dass das Testen auf ungerade / gerade Zahlen eingebaut ist. Angenommen, das $3enthält die zu testende Zahl und das Ergebnis geht in $2:

ZSEV $2,$3,1

setzt $2auf 1if$3 ist gerade und auf 0wenn nicht. Die mnemnoric ZSEVMittel Nullsatz selbst und hat folgende Semantik:

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

Für die obige Zeile mmixalGeneriert diese vier Assembler-Bytes:

7F 02 03 01
FUZxxl
quelle
3

Planen

Dies ist die ineffizienteste Lösung, die ich kenne.

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

Perl

Wie wäre es mit

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

JavaScript, 36

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

Gibt zurück, truewenn gerade, falsewenn nicht.

Ry-
quelle
2

Perl

$n x '0' =~ /^(00)*$/
Ming-Tang
quelle
2

Python

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

Testen Sie das Quadrat von i, damit es auch für negative Zahlen funktioniert

Knabberzeug
quelle
2

F #

Gegenseitige Rekursion um den Sieg.

Eine Zahl n ist gerade, wenn sie Null ist oder (n-1) ungerade ist.

Eine Zahl n ist ungerade, wenn sie ungleich Null ist und (n-1) gerade ist.

(abs hinzugefügt, falls jemand an der Parität negativer Zahlen interessiert ist)

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

Clojure

  (defmacro even?[n]
  `(= 1 ~(concat (list *) (repeat n -1))))
Benjie Holson
quelle
2

Was ist eine bitweise Operation? Unter der Haube wird die Ganzzahldivision durch 2 wahrscheinlich als Bitverschiebung implementiert.

Vorausgesetzt, es gibt keine Bitverschiebungen:

C / C ++

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

edit Verpasste einige Klammern und wurde letztendlich geändert, um eine Verschiebung zu entfernen, damit sie weniger funktioniert. Sie können dies mit den folgenden (in * nix) testen:

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

... obwohl ich in Linux / tcsh den Backslash on umgehen musste, \nobwohl er in einfachen Anführungszeichen stand. Ich habe in Little & Big-Endian getestet, es funktioniert in beiden Fällen korrekt. Auch das habe ich von Hand kopiert; Der Computer, auf dem ich poste, hat keinen Compiler, daher kann er Fehler enthalten.

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

oder

            shl  al, 7

oder

            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

... gefolgt von:

            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

Alternativ könnte das Shift & Compare-Zeug auch so gemacht werden:

            sar al,1            # signed integer division by 2 on least-significant byte
            jc  odd_label       # jump if carry flag is set
Brian Vandenberg
quelle
Übrigens, shlund Freunde sind nicht
erlaubt
2

Auf einem 68000-Prozessor können Sie einen Wortwert von der Adresse verschieben, die durch den zu testenden Wert definiert ist:

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

und lassen Sie die Hardwarefalle für Adressfehler die ungerade / gerade Art des Werts bestimmen - wenn die Ausnahme ausgelöst wird, war der Wert ungerade, wenn nicht, war der Wert gerade:

 <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

Funktioniert nicht auf Intel x86-CPUs, da diese beim Datenzugriff flexibler sind.

Skizz
quelle
2

Python

Ich entschied mich für die hässlichste und verwirrendste Lösung, die ich mir vorstellen konnte:

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]

Druckt e wenn gerade, o wenn ungerade.

scleaver
quelle
2

Q.

Subtrahiere 2 so lange, bis x <2 ist, und konvertiere dann zu bool

{1b$-[;2]/[2<=;abs x]}
Skeevey
quelle