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.


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

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')

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.

21

Mathematica

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

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

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]

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).


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"

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

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

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.


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.


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.

4

Rubin

n.odd?

Wenn Sie das Ergebnis ausdrucken möchten:

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

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


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.


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.


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

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

3

Perl

Wie wäre es mit

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

2

JavaScript, 36

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

Gibt zurück, truewenn gerade, falsewenn nicht.



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


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)


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

Ü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.


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.


2

Q.

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

{1b$-[;2]/[2<=;abs x]}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.