Ordine bit inverso di numeri interi a 32 bit


21

Scrivi il codice più breve per invertire l'ordine dei bit di un numero intero a 32 bit.

Regole:

  1. Si presume che l'input sia un numero intero valido o equivalente di stringa se la tua lingua non supporta valori numerici (ad es. Windows Batch).
  2. L'output deve essere un numero intero valido o equivalente stringa se la tua lingua non supporta valori numerici (ad es. Windows Batch).
  3. Solo libreria standard.
  4. Può essere una funzione o un programma completo.
  5. L'input può essere da stdino come argomento di funzione.
  6. L'output deve essere stdouto come valore restituito.
  7. Se la tua lingua ha una funzione di libreria integrata o standard che esegue questa operazione in un solo passaggio (ad esempio rbitnell'assemblaggio ARM), non può essere utilizzata.

Esempi:

Chiave:

  1. decimale
    • binario
    • (inverso)
    • binario invertito
    • uscita decimale

Esempi:

  1. -90 (Esempio a 8 bit per dimostrazione)

    • 10100110b
    • (inverso)
    • 01100101b
    • 101
  2. 486

    • 00000000000000000000000111100110b
    • (inverso)
    • 01100111100000000000000000000000b
    • 1736441856
  3. -984802906

    • 11000101010011010001100110100110b
    • (inverso)
    • 01100101100110001011001010100011b
    • 1704506019

Nota: le omissioni sono un gioco gratuito. Se non l'ho detto, e non è una delle scappatoie standard , allora è completamente permesso.


Cosa si intende per "omissioni" in "omissioni sono gioco libero"?
Todd Lehman,

1
Tutto quanto non esplicitamente indicato nelle regole.
Isiah Meadows,

Una tabella statica da 16 GB verrebbe conteggiata come parte della lunghezza del programma?
Hot Licks

@HotLicks Secondo l'interpretazione tipica del programma, sì.
FUZxxl,

linguaggio che supporta solo input a 8 bit, possiamo prendere input come quattro numeri a 8 bit?
Sparr,

Risposte:


0

assembly x86, 9 byte

    xor eax, eax
    inc eax
myloop:
    shr ecx, 1
    adc eax, eax
    jnc short myloop

In forma di byte: 33 C0 40 D1 E9 13 C0 73 FA9 byte.


Questo è esattamente quanto la mia soluzione se (a) obbedisci alla convenzione di chiamata cdecl e (b) effettivamente ritorni dalla funzione.
FUZxxl,

@FUZxxl In qualche modo, non ho visto la tua versione. Hai completamente ragione. Stavo pensando __fastcalle non avevo ret.
Myria,

24

Assemblaggio MMIX (28 byte)

Numeri a 64 bit

rbit:
    SETH $1,#0102 # load matrix in 16-byte steps
    ORMH $1,#0408
    ORML $1,#1020
    ORL  $1,#4080
    MOR  $0,$1,$0 # multiplication 1
    MOR  $0,$0,$1 # multiplication 2
    POP  1,0      # return

Questo si assembla a:

rbit:
    E0010102 # SETH $1,#0102
    E9010408 # ORMH $1,#0408
    EA011020 # ORML $1,#1020
    EB014080 # ORL  $1,#4080
    DC000100 # MOR  $0,$1,$0
    DC000001 # MOR  $0,$0,$1
    F8010000 # POP  1,0

Come funziona?

L' MORistruzione esegue una moltiplicazione di matrice su due quantità a 64 bit utilizzate come due matrici 8x8 di booleani. Un numero booleano con cifre abcdefghklmnopqr 2 viene utilizzato come matrice come questa:

/ abcd \
| efgh |
| klmn |
\ opqr /

L' MORistruzione moltiplica le matrici rappresentate dai loro argomenti in cui si trova la moltiplicazione ande l'addizione or. È:

/ 0001 \      / abcd \      / opqr \
| 0010 |  \/  | efgh |  --  | klmn |
| 0100 |  /\  | klmn |  --  | efgh |
\ 1000 /      \ opqr /      \ abcd /

e inoltre:

/ opqr \      / 0001 \      / rqpo \
| klmn |  \/  | 0010 |  --  | nmlk |
| efgh |  /\  | 0100 |  --  | hgfe |
\ abcd /      \ 1000 /      \ dcba /

che è l'ordine inverso dei bit del numero originale.

Numeri a 32 bit

Se vuoi solo il contrario di un numero a 32 bit invece di un numero a 64 bit, puoi utilizzare questo metodo modificato:

rbit:
    SETL   $1,#0408 # load first matrix in two steps
    ORML   $1,#0102
    MOR    $1,$1,$0 # apply first matrix
    SLU    $2,$1,32 # compile second matrix
    16ADDU $1,$2,$1
    MOR    $1,$0,$1 # apply second matrix
    POP    1,0      # return

assemblato:

rbit:
    E3010408 # SETL   $1,#0408
    EA010102 # ORML   $1,#0102
    DC010001 # MOR    $1,$1,$0
    3B020120 # SLU    $2,$1,32
    2E010201 # 16ADDU $1,$2,$1
    DC010001 # MOR    $1,$0,$1
    F8010000 # POP    1,0

La prima moltiplicazione matriciale funziona sostanzialmente in questo modo:

/ 0000 \      / 0000 \      / 0000 \
| 0000 |  \/  | 0000 |  --  | 0000 |
| 0001 |  /\  | abcd |  --  | efgh |
\ 0010 /      \ efgh /      \ abcd /

l'ottabita corrispondente è quello #0000000001020408che viene caricato nelle prime due istruzioni. La seconda moltiplicazione si presenta così:

/ 0000 \      / 0001 \      / 0000 \
| 0000 |  \/  | 0010 |  --  | 0000 |
| efgh |  /\  | 0100 |  --  | hgfe |
\ abcd /      \ 1000 /      \ dcba /

Il corrispondente ottabyte è quello #0102040810204080che creiamo dalla prima matrice in questo modo:

SLU $2,$1,#32   # $2 = #0102040800000000
16ADDU $1,$2,$1 # $2 = $2 + $1 << 4
                     = $2 + #0000000010204080
                #    = #0102040810204080

La seconda moltiplicazione è normale, il codice risultante ha la stessa lunghezza (28 byte).


1
è la prima volta che sento parlare delle istruzioni di moltiplicazione di matrici su una CPU
phuclv,

@ LưuVĩnhPhúc: non una moltiplicazione di matrici, ma VAX aveva un'istruzione per valutare un polinomio .
nneonneo,

1
@nneonneo Le POLYistruzioni del VAX sono fondamentalmente un multiplo-e-aggiungi fuso con un circuito integrato. Cose simili esistono anche nelle architetture moderne (come x86), ma di solito non hanno un ciclo integrato per valutare un intero polinomio contemporaneamente.
FUZxxl,

12

80386 assembly ( 13 12 byte)

Come funzione nella sintassi AT&T usando la convenzione di chiamata cdecl.

    # reverse bits of a 32 bit word
    .text
    .globl rbit
    .type rbit,@function
rbit:
    push $32       # prepare loop counter
    pop %ecx
0:  shrl 4(%esp)   # shift lsb of argument into carry flag
    adc  %eax,%eax # shift carry flag into lsb
    loop 0b        # decrement %ecx and jump until ecx = 0
    ret            # return

Questa funzione si monta alla seguente sequenza di byte:

6a 20 59 d1 6c 24 04 11 c0 e2 f8 c3

Suddiviso in istruzioni:

6a 20       push $32
59          pop %ecx
d1 6c 24 04 shrl 0x4(%esp)
11 c0       adc  %eax,%eax
e2 f8       loop .-6
c3          ret    

Funziona in questo modo: in ciascuna delle 32 iterazioni del loop, l'argomento, che si trova in 4(%esp), è spostato a destra di una posizione. L'ultimo bit viene implicitamente spostato nella bandiera carry. L' adcistruzione aggiunge due valori e aggiunge il valore del flag carry al risultato. Se aggiungi un valore a se stesso, ovvero %eaxlo sposti effettivamente a sinistra di una posizione. Questo rende adc %eax,%eaxun modo conveniente per spostare a sinistra %eaxdi una posizione mentre si sposta il contenuto della bandiera di trasporto nel bit di ordine inferiore.

Ripeto questo processo 32 volte in modo da 4(%esp)scaricare l'intero contenuto di %eax. Non ho mai inizializzato esplicitamente %eaxpoiché i suoi contenuti precedenti vengono spostati durante il ciclo.


+1 Grazie per la tua ultima frase, è ovvio ora ma mi sono perso.
edc65,

1
Sono sempre felice di vedere le soluzioni di assemblaggio qui :)
user1354557

8

C,    63    52   48

Versione originale:

int r(int n){int r=0,i=32;for(;i--;r=r<<1|n&1,n>>=1);return r;}

Versione aggiornata (con modifiche suggerite da Allbeert , es1024 e Dennis ):

r(n){int r,i=32;for(;i--;r=r*2|n&1,n>>=1);return r;}

Nota: poiché la seconda versione omette l'impostazione r=0, il codice presuppone che an intsia 32 bit. Se questo presupposto è falso, molto probabilmente la funzione produrrà un risultato errato, a seconda dello stato iniziale di raccesso alla funzione.


Versione finale (con ulteriori modifiche suggerite da Dennis e Alchymist ):

r(n,r,i){for(;32-i++;r=r*2|n&1,n>>=1);return r;}

Nota: questo inserisce la dichiarazione delle variabili di lavoro re inell'elenco dei parametri. I parametri sono i seguenti: nè il numero da invertire i bit. re isono variabili di lavoro che devono essere passate come 0.


1
È possibile rimuovere il inttipo di funzione e anche passare return ra qualcosa di simile i=rpoiché la maggior parte dei compilatori C tende a lasciare il risultato dell'ultima operazione nel registro di ritorno. Ha funzionato su gcc e cl per me.
Allbeert,

1
Potresti radere altri 4 byte usando r(n){...}invece dir(int n){...}
es1024

2
@FUZxxl non è possibile cadere la inta int r=0,i=32;meno che non li sposta fuori del corpo della funzione.
es1024,

1
@FUZxxl: Non dovrei commentare quando sono stanco ... Il cambiamento e la divisione aritmetica non sono equivalenti; il secondo è arrotondato allo zero, mentre il primo è arrotondato all'infinito negativo. -1 >> 1è -1per AS e 2**31 - 1per LS, mentre lo -1 / 2è 0.
Dennis,

1
@Todd: qualche motivo che non hai definito re icome argomenti? Salverebbe altri tre byte ...
Dennis,

5

Julia 0,2, 33 byte

f(n)=parseint(reverse(bits(n)),2)

Fa quello che sembra.

bitsti dà la rappresentazione dei bit (rispettando il complemento a due). parseintnon si preoccupa del complemento a due, ma restituisce un numero intero a 32 bit, quindi il complemento a due viene semplicemente gestito dall'overflow.

Secondo i log delle modifiche, il rilevamento di overflow è stato aggiunto parseintin Julia 0.3, quindi potrebbe non funzionare più.


5
Questo è un codice di produzione, non un codice golf! xD Immagino che Julia sia semplicemente fantastica.
cjfaure,

4

Python 2, 50

print int("{:032b}".format(input()%2**32)[::-1],2)

In generale lo stesso della mia soluzione Pyth. Prendi l'ingresso mod 2 ** 32, converti in binario imbottito a 32 bit, inverti, converti la puntura binaria in decimale e stampa.


4

CJam, 15 byte

li4H#+2bW%32<2b

Provalo online.

Joker "Gioco libero" utilizzato: L'output sarà sempre un numero intero senza segno .

Casi test

$ cjam reverse32.cjam <<< 486; echo
1736441856
$ cjam reverse32.cjam <<< -984802906; echo
1704506019

Come funziona

li   " Read from STDIN and cast to integer. ";
4H#+ " Add 4 ** 17 to avoid special cases. ";
2b   " Convert into array of digits in base 2. ";
W%   " Reverse the order. ";
32<  " Discard the 33th and all following digits. ";
2b   " Convert the array of digits into an integer. ";

4

JavaScript (E6) 37 39 40 50

Funzione, numero inserito e numero inverso di ritorno. La maggior parte degli algoritmi di base, probabilmente può essere giocata più a golf con qualche trucco intelligente.

Modifica ricorsione invece di ciclo

Modifica 2 Seguendo il suggerimento di @bebe k*2invece dik<<1

Modifica 3 Qualcosa che mi mancava del tutto: è un loop a 32 bit completo, non è necessario inizializzare k. Grazie @FUZxxl

R=(v,b=32,k)=>b?R(v>>1,b-1,k*2|v&1):k

Era

R=v=>{for(k=b=0;b++<32;)k+=k+(v&1),v>>=1;return k}

Test Nella console FireFox, testare usando numeri in OP e alcuni altri numeri casuali a 16 e 32 bit

Bin=x=>('0'.repeat(32)+(x<0?-x-1:x).toString(2)).slice(-32).replace(/./g,d=>x>0?d:1-d),
Dec=x=>(' '.repeat(11)+x).slice(-11),
R16=_=>Math.random()*65536|0,  
R32=_=>(Math.random()*65536<<16)|R16(),  
[-90,486,-984802906,R16(),R16(),R16(),R32(),R32(),R32(),R32()]
 .forEach(n=> console.log(Dec(n)+' '+Bin(n)+' '+Dec(R(n))+' '+Bin(R(n))))

Esempio di uscita di prova

        -90 11111111111111111111111110100110  1711276031 01100101111111111111111111111111
        486 00000000000000000000000111100110  1736441856 01100111100000000000000000000000
 -984802906 11000101010011010001100110100110  1704506019 01100101100110001011001010100011
      45877 00000000000000001011001100110101 -1395851264 10101100110011010000000000000000
      39710 00000000000000001001101100011110  2027487232 01111000110110010000000000000000
      56875 00000000000000001101111000101011  -730136576 11010100011110110000000000000000
-1617287331 10011111100110100010011101011101 -1159439879 10111010111001000101100111111001
-1046352169 11000001101000011110111011010111  -344488573 11101011011101111000010110000011
 1405005770 01010011101111101010111111001010  1408597450 01010011111101010111110111001010
  -35860252 11111101110111001101000011100100   655047615 00100111000010110011101110111111

b=k=0,R=v=>b++<32?R(v>>1,k+=k+(v&1)):kper uso singolo ed R=(v,b=0,k=0)=>b<32?R(v>>1,b+1,k+k+(v&1)):kè riutilizzabile
bebe

@bebe :( Stavo rivedendo la mia risposta usando la ricorsione e ho perso tutto per leggere il tuo commento ...
edc65

2
sei a 38 byte se k<<1diventa k*2e v>>1diventa v/2. ha funzionato per 486. Non conosco altri casi di test
bebe

1
@bebe v / 2 non funzionerà con numeri negativi. 486/512 == 0.9 ... e 486 >> 9 == 0, troncare è lo stesso. Ma -90/128 == -0,7 ... e -90 >> 7 == - 1
edc65

4

x86 assemply, 10 byte

   f9                      stc    
   d1 d8            1:     rcr    %eax
   74 05                   je     2f
   d1 d2                   rcl    %edx
   f8                      clc    
   eb f7                   jmp    1b
                    2:

Ciò presuppone input in eax, output in edx. (Inoltre, sull'output eax è zero e sono impostati CF e ZF, se qualcuno se ne frega).

Invece di un contatore, un ulteriore 1 viene inserito all'inizio come marker di fine dati


Questo ha effettivamente le stesse dimensioni della mia soluzione, che è di tre byte più grande. Se si aggiungono le retistruzioni per tornare dalla funzione e si implementa cdecl (ovvero si cambia rcr %eaxin rcr 4(%esp)e rcl %edxin rcl %eax), si finisce con un byte in più per il rete altri due byte per il riferimento di memoria. Comunque, una bella soluzione.
FUZxxl,

3

J ( 17 15 13 byte)

_32#.@|.@{.#:

Ecco una definizione esplicita per spiegare cosa fa:

3 : '#. |. _32 {. #: y'
  1. #: yrappresenta yun numero di base 2 utilizzando tutti i posti necessari.
  2. x {. yprende |x(magnitudo di x) elementi da y, se xè positivo dalla parte anteriore , da se xè negativa dalla parte posteriore . Se prendiamo più oggetti del presente, il risultato viene riempito con zero. _32 {. #: yefficacemente pad #: ya 32 bit.
  3. |. ycapovolge y, io. inverte l'ordine degli articoli in y.
  4. #. y interpreta ycome un numero base-2.


2

Python - 89

def r(n):
 if n<0:n=~n^0xFFFFFFFF
 print int(['','-'][n%2]+'{:032b}'.format(n)[::-1],2)

Python rappresenta semplicemente numeri binari negativi -0b{positive_number}. Quindi, per far fronte a questo, completa i numeri negativi e poi XOR con tutti gli 1.

Successivamente, crea la rappresentazione in formato stringa dell'intero in base al formato {:032b}che fornisce la rappresentazione a 32 bit del numero. Infine, inverti la stringa e trasformala di nuovo in un numero intero.

MODIFICARE

Grazie a @Martin Büttner per aver segnalato il problema del complemento a due. Se ntermina con un 1, allora con il complemento a due la versione invertita sarebbe negativa.

Fortunatamente, come spiegato sopra, a Python piacciono i numeri binari negativi in ​​un modo abbastanza semplice. Fortunatamente, la intfunzione di Python consente caratteri di segno opzionali nel suo primo argomento.

Quindi ora aggiungi un segno meno se nè dispari per soddisfare il complemento a due.


@ MartinBüttner Grazie. All'inizio ho perso quella possibilità. Il nuovo codice gestisce meglio il complemento a due.
BeetDemGuise

2
Puoi giocare a golf un po 'di più: ['','-'][n%2]è '-'*(n%2).
Giustino,

2

Pyth , 33 32 22

v_%"%032db0"vsc%Q^2 32

Spiegazione:

                 Q             Evaluated input.
                %Q^2 32        Q mod 2^32. Same 32 bit binary representation as Q.
             vsc%Q^2 32        Convert to binary string, then that to decimal int.
   %"%032db0"vsc%Q^2 32        Pad above number to 32 bits, and append b0.
  _%"%032db0"vsc%Q^2 32        Reverse it.
 v_%"%032db0"vsc%Q^2 32        Eval and print. Due to leading "0b", eval as binary.

golf:

33 -> 32: spostato aggiungi a prima di invertire per salvare un preventivo.

32 -> 22: usato Q mod 2 ^ 32 invece di macchinari complicati. Combina entrambe le stringhe in una.

Casi test:

$ cat rev_bits 
v_%"%032db0"vsc%Q^2 32

$ ./pyth.py rev_bits <<< -984802906
1704506019

$ ./pyth.py rev_bits <<< 486
1736441856

$ ./pyth.py rev_bits <<< 0
0

Funziona con il risultato come 32 grandi numeri con il bit più a sinistra su 1? In questo caso dovrebbe generare un numero intero negativo.
edc65,

@ edc65 Sto inviando un numero intero senza segno a 32 bit.
isaacg,

2

GNU cc, 27 byte

0?[2~rssr2*+dlsz34>m]dsmx+p

Produzione:

$ dc revbits.dc <<< 15
4026531840
$ dc revbits.dc <<< 255
4278190080
$ dc revbits.dc <<< 65535
4294901760
$ dc revbits.dc <<< 4294901760
65535
$ dc revbits.dc <<< 4278190080
255
$ dc revbits.dc <<< 4026531840
15
$ 

Bash + coreutils, 45 byte

n=`dc -e2do32^n$1p`
dc -e2i`rev<<<${n: -32}`p

Produzione:

$ ./revbits.sh 15
4026531840
$ ./revbits.sh 255
4278190080
$ ./revbits.sh 65535
4294901760
$ ./revbits.sh 4294901760
65535
$ ./revbits.sh 4278190080
255
$ ./revbits.sh 4026531840
15
$ 

Funzione C, 89 byte

Stessa idea di /codegolf//a/36289/11259 - utilizzando gli hack di twiddling bit di Stanford . Non vincerà il golf, ma comunque interessante:

// 89 byte function:
i;r(v){for(i=1;i<32;i*=2)v=v>>i&(1L<<32)/((1<<i)+1)|(v&(1L<<32)/((1<<i)+1))<<i;return v;}

// Test program:
#include <stdio.h>

int main (int argc, char **argv)
{
    printf("r(0x0000000f) = 0x%08x\n", r(0x0000000f));
    printf("r(0x000000ff) = 0x%08x\n", r(0x000000ff));
    printf("r(0x0000ffff) = 0x%08x\n", r(0x0000ffff));
    printf("r(0xffffffff) = 0x%08x\n", r(0xffffffff));
    printf("r(0x0f0f0f0f) = 0x%08x\n", r(0x0f0f0f0f));
    printf("r(0xf0f0f0f0) = 0x%08x\n", r(0xf0f0f0f0));
}

Produzione:

$ ./revbits 
r(0x0000000f) = 0xf0000000
r(0x000000ff) = 0xff000000
r(0x0000ffff) = 0xffff0000
r(0xffffffff) = 0xffffffff
r(0x0f0f0f0f) = 0xf0f0f0f0
r(0xf0f0f0f0) = 0x0f0f0f0f
$

2

Funzione Java, 64 caratteri.

 int r(int n){int r=0,i=32;for(;i-->0;n>>=1)r=r<<1|n&1;return r;}

Dovrebbe funzionare anche in C.


2

PHP, 46 byte

Versioni online

for(;$i<32;)$t.=$argn>>$i++&1;echo bindec($t);

o

<?=bindec(strrev(sprintf("%064b",$argn<<32)));

Non substrè necessario (-12 byte). Dovresti menzionare come eseguirli.
Tito,

1
@Titus hai provato la testcase -984802906?
Jörg Hülsermann,

1
La tua seconda versione può essere migliorata per corrispondere alla prima:<?=bindec(strrev(sprintf("%064b",$argn<<32)));
Christoph,

@Christoph miglioramento molto bello Grazie
Jörg Hülsermann,

1

JS 115

Beh, questo non sembra affatto buono: D

n=+prompt();alert(eval('0b'+(Array(33).join(0)+(n<0?n>>>0:n).toString(2)).slice(-32).split('').reverse().join('')))

Il metodo di @Florian F in JS è lungo 53 byte:

for(n=+prompt(r=0),i=32;i--;n>>=1)r=r<<1|n&1;alert(r)

1
La it may be a functionregola significa che non è necessario l'avviso o il prompt
slebetman,

1

C # 81 74

int R(int V){int l,r=l=0,i=1;for(;i>0;i*=2)r|=i*(1&V>>(31-l++));return r;}

Operazioni bit che molto probabilmente possono essere eseguite in modo più breve in tutti i linguaggi di programmazione.

Fondamentalmente, passa in rassegna tutte le potenze da 2 fino a un numero intero massimo + 1 (che si trasforma in una potenza di due) e poiché (2.147.483.647 + 1) = 0 posso fare un ciclo a 0. Spostamento bit Da sinistra a destra per spostare il bit nel primo posizione. L'ultimo bit al posto 32 fa 31 passi a destra, il secondo ultimo va a 30 ecc. Quindi usando l'operatore AND con 1 saprò se è 1 o 0. Se è 1 aggiungerò il valore i attuale al risultato e restituirlo.

int R(int V)
{
    int l,r=l=0,i=1;
    for(;i>0;i*=2)
        r|=i*(1&(V>>(31-l++)));
    return r;
 }

Piccole cose, ma puoi inizializzare iquando lo dichiari e salvare un byte rimuovendo i++dal ciclo for, e invece di confrontare il risultato di 1&...con 0 puoi rimuovere completamente l'istruzione if e moltiplicarla iper il risultato che dà r|=i*(1&(V>>(31-l++)));all'interno del ciclo
VisualMelon

Intelligente! Avevo la sensazione che mi mancasse qualcosa. Grazie!
WozzeC,

1

C # 142

using System;using System.Linq;int f(int n){return Convert.ToInt32(new string(Convert.ToString(n,2).PadLeft(32,'0').Reverse().ToArray()),2);}

allargato

int f(int n)
{
    return Convert.ToInt32(
        new string(
            Convert.ToString(n, 2)
            .PadLeft(32, '0')
            .Reverse()
            .ToArray()), 2);
}

1

Python - 37

Simile alla soluzione di @ isaacg.

f=lambda n:int(bin(n%2**32)[:1:-1],2)

1

C ++, 160

Questo non è il più breve, tuttavia utilizza solo 24 operazioni.
Tratto dal libro Hacker's Delight.

golfed:

typedef unsigned U;U R(U&x){U a=-1u/3,b=-1u/5,c=-1u/17,d=65280;x=(x&a)*2|(x/2)&a;x=(x&b)*4|(x/4)&b;x=(x&c)<<4|(x>>4)&c;x=(x<<24)|((x&d)<<8)|((x>>8)&d)|(x>>24);}

Ungolfed:

unsigned R(unsigned x) {
    x = (x & 0x55555555) <<  1 | (x >>  1) & 0x55555555; 
    x = (x & 0x33333333) <<  2 | (x >>  2) & 0x33333333; 
    x = (x & 0x0F0F0F0F) <<  4 | (x >>  4) & 0x0F0F0F0F; 
    x = (x << 24) | ((x & 0xFF00) << 8) | ((x >> 8) & 0xFF00) | (x >> 24); 
    return x; 
} 

1
Questa è una domanda di golf del codice. Prova a ridurre il numero di caratteri nella tua soluzione, non il numero di operazioni.
FUZxxl,

1

Haskell, 145 - nessuna operazione bit a bit

Il bit-twiddling mi sembra l'antitesi di Haskell, quindi ho evitato qualsiasi uso di operatori bit per bit. Il programma risultante non è certamente il concorrente più breve, ma ho pensato che l'uso della matematica invece del bit-twiddling fosse interessante almeno.

import Data.Tuple
import Data.List
f m=foldl1((+).(*2))$take 32$(unfoldr(\n->if n==0 then Nothing else Just$swap$divMod n 2)$mod m$2^32)++[0,0..]

Spiegazione

f m=foldl1((+).(*2))$take 32$(unfoldr(\n->if n==0 then Nothing else Just$swap$divMod n 2)$mod m$2^32)++[0,0..]
    |------5-------|---4----|--------------------------2---------------------------------|----1-----|---3----|
  1. utilizza il modulo per portare il risultato nell'intervallo a 32 bit
  2. costruisce un elenco di 0s e 1s, il bit meno significativo per primo dividendo ripetutamente per 2 e prendendo il resto
  3. concatena un elenco infinito di 0s alla fine di questo elenco
  4. prende i primi 32 elementi dell'elenco (questi ultimi due erano necessari per garantire che l'elenco fosse effettivamente lungo 32 bit).
  5. converte un elenco di 0e 1in un numero intero assumendo che il bit più significativo sia il primo (ripetuto doppio e aggiungi).

Non sono del tutto sicuro di cosa costituisca la "libreria standard" in Haskell, quindi ho pensato che Data.Tuple e Data.List fossero OK (sono piuttosto standard).

Inoltre, l'output è un numero intero a 32 bit senza segno poiché la modifica che mi costerebbe byte: sto discutendo questo sotto "omissioni sono gioco libero".


Libreria standard: cosa viene fornito con la lingua. Ciò include le intestazioni di sistema per C, le classi e i metodi 4000+ in Java (la maggior parte sono irrilevanti).
Isiah Meadows,

1

PHP, 46 41 byte

provali online

while($i<32)$r=$r*2|$argn>>$i++&1;echo$r;

bit a bit ... più o meno. Esegui come pipe con php -nR '<code>'.

PHP, 46 byte

while($i<32)$r|=($argn>>$i&1)<<31-$i++;echo$r;

una soluzione bit a bit pura; correre come tubo con -nR.

PHP, 47 59 byte

<?=bindec(str_pad(strrev(substr(decbin($argn),-32)),32,0));

un altro approccio integrato; salva su file ed esegui come pipe con -F.


0

Perl - 60

$_=unpack"N",pack"B*",scalar reverse unpack"B32",pack"N",$_

+1 per la bandiera p (fammi sapere se sto contando questo errore).

Corri con:

echo 486 | perl -pe'$_=unpack"N",pack"B32",scalar reverse unpack"B32",pack"N",$_'

0

C ++ 69

int r(int n){int e=0,i=0;for(;i<32;i++)e|=((n>>i)&1)<<31-i;return e;}

@bebe cosa sono questi e;i;? Le dichiarazioni senza tipo non sono un C ++ valido. Per le variabili non è nemmeno valido C.
Ruslan,

@Ruslan non ho riconosciuto '++' nel titolo, scusa. (Non sarei d'accordo con la tua seconda affermazione)
Bebe

int r(int n){int e=0,i=0;for(;i<32;)e=e*2|1&n>>i++;return e;}61 byte :)
Christoph,

0

R, 45

f=function(x)packBits(intToBits(x)[32:1],"i")

Esempi:

f(486)
# [1] 1736441856
f(-984802906)
# [1] 1704506019

Sempre solo timido rispetto alle risposte di Python. Quella dannata parola chiave funzione.


0

Rubino, 43 41 byte

def r(n)(0..31).inject(0){|a,b|a*2+n[b]}end

In Ruby, usando la notazione dell'indice di parentesi (foo [i]) si restituisce il bit all'ennesima posizione.

--Modificare--

Il refactoring della injectfunzionalità rade un paio di byte

def r(n)z=0;32.times{|i|z=z*2+n[i]};z;end


0

Perl5: 46

sub r{for(0..31){$a=$a*2|$_[0]&1;$_[0]>>=1}$a}

Nulla di bello. Sposta l'output a sinistra, copia lsb prima di spostare l'origine a destra.


0

Clojure, 202 156 142

#(read-string (let [s (clojure.pprint/cl-format nil "~2r" %)](apply str (reverse (apply str (concat (repeat (- 32 (count s)) "0") s "r2"))))))

0

Perl (37 + 1)

fondamentalmente un porto della soluzione C di Todd Lehman

perl -E '$t=<>;map$r=2*$r|1&$t>>$_,0..31;say$r'

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.