Comment déterminer si un nombre est impair ou même sans opérations mod ou bit à bit? [fermé]

19

Comment déterminer si un nombre est impair ou même sans opérations mod ou bit à bit?

Ce défi est extrêmement inefficace, mais remet en question votre capacité à sortir des sentiers battus pour une solution créative.

MODIFIER :

Veuillez créer une fonction. De plus, bien que l'expression régulière soit une réponse amusante, la fonction doit accepter n'importe quel nombre valide.

CONTEXTE : Cette question découle de mes premiers jours de programmation. Les devoirs pour notre premier jour de classe étaient d'écrire un programme simple qui imprimait «impair» ou «pair». Étant le gamin que j'étais, je n'ai pas lu le livre que nous avions pour la classe où il nous montrait simplement comment l'utiliser%pour déterminer cela. J'ai passé environ une demi-heure à faire les cent pas dans ma chambre en essayant de penser à un moyen de le faire et je me suis souvenu de la conférence que les nombres peuvent perdre et gagner en précision car ils sont castés d'un type primitif à un autre. Par conséquent, si vous preniez le nombre, le divisiez par deux, puis le multipliez en arrière, ce n'était pas le nombre d'origine, alors vous sauriez que le nombre était impair.

J'ai été stupéfait le lendemain, alors que notre instructeur évaluait nos programmes, qu'il pensait que c'était la façon la plus originale, mais inefficace, de résoudre le problème.

Wayne Hartman
la source
3
Faut-il créer une fonction ou un programme? Comment cela devrait-il arriver si nous devons faire un programme? Veuillez développer davantage.
Juan
2
Quel critère objectif déterminera la réponse acceptée? Taille du code? Autre chose?
PleaseStand
Est-ce vraiment un chiffre? Doit-il donner des faux positifs pour une chaîne?
William
Cela existe depuis assez longtemps, mais il ne semble pas y avoir de condition gagnante, ce qui, à mon avis, signifie qu'il n'y a pas de jeu ici.
dmckee

Réponses:

40

Dans la plupart des langages de programmation, la division renvoie un quotient pour les entiers. Vous pouvez donc simplement vérifier cela

(i/2)*2==i
fR0DDY
la source
6
Pas nécessairement la plupart, je dirais. Beaucoup, peut-être.
Joey
1
pour vous assurer qu'il fonctionne correctement, vous devez vous assurer que vous avez tout jeté dans un int/ longtype
warren
@warren Dépend des optimisations du langage de programmation / du compilateur / etc. De plus, vous pouvez utiliser floor(). Cela fonctionne parfaitement en C et C ++.
Mateen Ulhaq
1
0 est-il un nombre pair?
utilisateur inconnu
4
@userunknown: Oui, zéro est pair.
Keith Thompson
71

Python

print('even' if (-1)**n==1 else 'odd')
dan04
la source
10
La beauté simple / belle simplicité des mathématiques ... très sympa!
jscs
J'aime beaucoup celui-ci.
Rob
Lent mais créatif.
Mateen Ulhaq
21

Brainf *** (179)

C'est l'un des problèmes les plus intéressants concernant la logique conditionnelle que j'ai fait dans BF.

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

Il faut une entrée de texte avec un nombre. Si le nombre est pair, il sort E, et s'il est impair, il sort O.

J'en suis assez fier pour montrer une forme plus lisible:

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

Mathematica

SawtoothWave[x / 2] == 0
Exp[I Pi x] - 1 == 0
Sin[5 x / Pi] == 0
Ming-Tang
la source
2
Pouvez-vous diviser ces deux solutions en différentes réponses?
FUZxxl
Ces quatre solutions ne sont-elles pas?
Joey
En fait, tous les noms intégrés dans Mathematica sont en majuscule, donc aussi drôle que cela puisse paraître, vous devez utiliser Iet Piau lieu de iet pi.
David Zhang
15

C

Multiplié par lui-même plusieurs fois, tout nombre pair débordera à 0 étant donné un entier de taille finie, et tout nombre impair continuera d'avoir au moins le bit le moins significatif défini.

#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: Comme une fonction simple:

int isOdd(long long input){
    int a;
    for(a=6;a;a--){
        input*=input;
    }
    return !!input;
}
aaaaaaaaaaaa
la source
Assurez-vous d'utiliser des entiers non signés. Le débordement d'entiers signés est un comportement non défini en C, donc l'optimisation pourrait faire quelque chose de bizarre si elle le voulait.
Joey Adams
13

Python (lent)

n=1234
while n > 1: n -= 2 #slow way of modulus.
print "eovdedn"[n::2]
st0le
la source
1
Fonctionne pour positif ... je suppose que je pourrais ajouter un abs()appel au début.
st0le
@Josh: Cette astuce est apparue ici plusieurs fois déjà :)
Joey
Crédits à gnibblr :)
st0le
@Joey: Je ne pensais pas que c'était nouveau, mais le style n'a pas besoin d'être original. :)
jscs
12

Javascript

/[02468]$/.test(i)

donne trueun nombre pair. Cela ne fonctionne qu'avec des entiers de taille raisonnable (par exemple, pas de notation scientifique lorsqu'ils sont convertis en chaîne et n'ayant pas de partie fractionnaire.)

Veuillez vous lever
la source
2
Pour répondre à l'exigence de "fonction", vous pouvez la changer simplement /[02468]$/.test.
Ry-
Ce n'était pas exactement clair dans la question, mais il pourrait être possible que l'entrée ne soit pas du tout un nombre /[02468]$/.test('I am a fake even number 0'). Dans ce cas, vous pourriez le faire/^[0-9].[02468]$/.test(i)
William
/-?^\d*[02468]$/serait un peu plus strict que votre regex. Vous auriez besoin de plus de travail pour que cela fonctionne correctement pour les nombres qui sont toString'ed en utilisant la notation scientifique.
Thomas Eding
12

Python

Comme je ne sais pas vraiment quels sont les critères de notation, voici un tas de solutions que j'ai trouvées pour le plaisir. La plupart d'entre eux utilisent abs(n)pour supporter des nombres négatifs. La plupart d'entre eux, sinon tous, ne doivent jamais être utilisés pour un calcul réel.

Celui-ci est un peu ennuyeux:

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"

Et c'est mon préféré bien que cela ne fonctionne malheureusement pas (comme le souligne March Ho ci-dessous: le fait que tous les nombres pairs soient la somme de deux nombres premiers ne signifie pas que tous les nombres impairs ne le sont pas).

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
la source
Solutions mignonnes :-)
Joey
2
Vraiment une vieille nécro, mais la réponse de votre conjecture de Goldbach ne s'imprime-t-elle pas Même pour 9? Semble comme un cas d' affirmation de l'erreur fallacieuse qui en résulte
March Ho
Oui, vous avez absolument raison à cent pour cent, @MarchHo. Oeuf sur mon visage.
jscs
10

Haskell

Bien sûr, ce n'est en aucun cas la solution créative et hors des sentiers battus que vous recherchez, mais combien de fois vais-je pouvoir publier une réponse Haskell plus courte que GolfScript, vraiment? C'est vraiment dommage que ce ne soit pas un golf de code.

odd

Mais plus sérieusement:

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

la source
semble plus long que la réponse GolfScript pour moi
warren
2
Je faisais référence au premier bloc ( odd) qui est une fonction intégrée qui renvoie True si le nombre est impair. C'est une réponse complète en elle-même et plus courte que la réponse GolfScript actuelle (qui au moment de la rédaction, c'est 10 caractères, mais je m'attends à ce que cela baisse). La question est également un peu sous-spécifiée, c'est pourquoi j'affirme que oddc'est suffisant. Cela pourrait également changer.
1
a manqué la première réponse dans votre réponse :)
warren
1
À tout le moins, l' parityalgorithme fonctionne sur toutes les Numinstances qui sont des entiers. C'est chaud! Bien que je l'aurais probablement fait evens = [0,2..] >>= \n -> [-n, n]. Similaire pour les cotes.
Thomas Eding
7

En utilisant une lecture délibérément perverse de la question, "Comment déterminer si un nombre est impair ou pair", voici une implémentation C (supposons boolet truesont définis de manière appropriée):

bool is_odd_or_even(int n)
{
    return true;
}
Keith Thompson
la source
La question mentionne un nombre, pas un entier. Nombre comme les 0.5retours truealors qu'il ne devrait pas.
Konrad Borowski
6

Quoi, pas encore d'algorithmes randomisés ??

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

Associe au hasard des nombres compris entre 0 et n -1 jusqu'à ce qu'il reste moins de 2. Il est tout à fait étonnamment inefficace: O ( n 3 ).


Complètement différent:

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

Utilise le fait que la transformée de Fourier d'une fonction paire (par exemple \x->x^^4) est réelle, tandis que la transformée de Fourier d'une fonction impaire est imaginaire.

a cessé de tourner dans le sens antihoraire
la source
5

Windows PowerShell

function OddOrEven([long]$n) {
  if (0,2,4,6,8 -contains "$n"[-1]-48) {
    "Even"
  } else {
    "Odd"
  }
}
  1. Convertir en chaîne
  2. Choisissez la dernière lettre (chiffre) (essentiellement un mod 10).
  3. Vérifiez s'il s'agit de 0, 2, 4, 6 ou 8.

Pas d'opérateurs au niveau du bit, pas de module, comme demandé.

Joey
la source
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.

Pour autant que je sache, c'est la première entrée coq sur codegolf.

Encore plus court (59):

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

Rubis

n.odd?

Si vous souhaitez imprimer le résultat:

f[n] = ->(n){puts n.odd?? 'odd' : 'even'}
Lowjacker
la source
J'utilise assez ruby ​​utilise le mod dans la .odd?définition.
MrZander
4

Unlambda

Le monde a besoin de plus d'Unlambda.

Unlambda a un avantage décisif ici: sa représentation par défaut ( ahem ) pour les nombres sont des chiffres d'église, donc tout ce qui est nécessaire est de les appliquer à la fonction binaire - pas à la fonction true. Facile!

PS: Markdown et Unlambda ne sont certainement pas faits l'un pour l'autre.

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

Vérification des premiers nombres entiers:

```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
la source
3

Golfscript

~,2/),1=\;
VOUS
la source
3

Python

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

Performances similaires à la version précédente. Fonctionne pour 0 maintenant.

Version antérieure incorrecte:

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

Pas particulièrement efficace; temps et mémoire évidemment O (n): 32 ms pour 1 000 000; 2,3 ms pour 100 000; 3.2 usec pour 100. Fonctionne avec des nombres négatifs. Lance une erreur pour 0, car 0 n'est ni pair ni impair.

jscs
la source
3
Zéro est définitivement égal. Voir aussi: en.wikipedia.org/wiki/Parity_of_zero
@jloy: Aw, merde. Je pensais que c'était "une fonctionnalité, pas un bug". Plus de révisions ...
jscs
3

Fractran

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

appliqué à

63*2^abs(n)

donne 5si nest impair ou 1si nest pair.

Mise à jour : beaucoup plus courte mais pas si intéressante:

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

est 2pour impair net 1pour pair n.

Howard
la source
3

MMIX (4 octets)

C'est une sorte de tricherie. Je n'utilise ni mod ni bit fiddling. C'est plutôt que le test des nombres pairs / impairs est intégré. En supposant que $3contient le nombre à tester et que le résultat entre dans $2:

ZSEV $2,$3,1

ensembles $2à s'est encore et à sinon. La mnémorique signifie pair à zéro et a la sémantique suivante:1$30ZSEV

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

Pour la ligne ci-dessus, mmixalgénère ces quatre octets d'assemblage:

7F 02 03 01
FUZxxl
la source
3

Schème

C'est la solution la plus inefficace que je connaisse.

(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
la source
3

Perl

Qu'en est-il de

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

JavaScript, 36

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

Renvoie truesi pair, falsesinon.

Ry-
la source
2

Perl

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

Python

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

tester le carré de i, donc ça marche aussi pour les nombres négatifs

grignoteur
la source
2

F#

Récursion mutuelle pour la victoire.

Un nombre n est pair s'il est nul ou (n-1) est impair.

Un nombre n est impair s'il est différent de zéro et (n-1) est pair.

(abs ajouté au cas où quelqu'un serait intéressé par la parité des nombres négatifs)

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

Clojure

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

Qu'est-ce qui constitue des opérations au niveau du bit? Sous le capot, la division entière par 2 est susceptible d'être implémentée comme un décalage binaire.

En supposant que les décalages de bits ne sont pas sortis:

C / C ++

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

edit Manqué quelques parenthèses, et finalement changé pour supprimer un décalage pour le faire moins. Vous pouvez tester cela avec les éléments suivants (dans * 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

... bien que sous Linux / tcsh, j'ai dû échapper à la barre oblique inverse \nmême si elle était entre guillemets simples. J'ai testé en little & big-endian, cela fonctionne correctement dans les deux. Aussi, j'ai copié ceci à la main; l'ordinateur avec lequel je poste n'a pas de compilateur, il peut donc y avoir des erreurs.

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

ou

            shl  al, 7

ou

            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

... suivi par:

            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

Alternativement, le changement et la comparaison peuvent également être effectués de cette façon:

            sar al,1            # signed integer division by 2 on least-significant byte
            jc  odd_label       # jump if carry flag is set
Brian Vandenberg
la source
BTW shlet ses amis ne sont pas autorisés ...
FUZxxl
2

Sur un processeur 68000, vous pouvez déplacer une valeur de mot de l'adresse définie par la valeur à tester:

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

et laissez le piège matériel pour l'erreur d'adresse déterminer la nature paire / impaire de la valeur - si l'exception est levée, la valeur était impaire, sinon, la valeur était paire:

 <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

Ne fonctionne pas sur les processeurs Intel x86 car ceux-ci sont plus flexibles sur l'accès aux données.

Skizz
la source
2

Python

J'ai décidé d'essayer la solution la plus laide et la plus déroutante à laquelle je pouvais penser:

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]

Imprime e s'il est pair, o s'il est impair.

scleaver
la source
2

Q

Continuez à soustraire 2 jusqu'à ce que x <2 puis convertissez en bool

{1b$-[;2]/[2<=;abs x]}
skeevey
la source