Die Basis des Doppels

12

Hintergrund

IEEE 754 Gleitkommaformat mit doppelter Genauigkeit ist eine Möglichkeit, reelle Zahlen mit 64 Bit darzustellen. Es sieht so aus:

Eine reelle Zahl nwird doublefolgendermaßen in eine umgewandelt :

  1. Das Vorzeichenbit sist 0, wenn die Zahl positiv ist, andernfalls 1.
  2. Der Absolutwert von nwird in der Form dargestellt 2**y * 1.xxx, dh eine Potenz von 2 mal einer Basis .
  3. Der Exponent eist y(die Potenz von 2) minus 1023.
  4. Der Bruch fist der xxxTeil (Bruchteil der Basis), der die höchstwertigen 52 Bits belegt.

Umgekehrt repräsentiert ein Bitmuster (definiert durch Vorzeichen s, Exponent eund Bruch f, jeweils eine ganze Zahl) die Zahl:

(s ? -1 : 1) * 2 ** (e - 1023) * (1 + f / (2 ** 52))

Herausforderung

Bei einer reellen Zahl nwird der 52-Bit-Bruchteil der doubleDarstellung nals Ganzzahl ausgegeben .

Testfälle

0.0        =>                0
1.2        =>  900719925474099 (hex 3333333333333)
3.1        => 2476979795053773 (hex 8cccccccccccd)
3.5        => 3377699720527872 (hex c000000000000)
10.0       => 1125899906842624 (hex 4000000000000)
1234567.0  =>  798825262350336 (hex 2d68700000000)
1e-256     => 2258570371166019 (hex 8062864ac6f43)
1e+256     => 1495187628212028 (hex 54fdd7f73bf3c)

-0.0       =>                0
-1.2       =>  900719925474099 (hex 3333333333333)
-3.1       => 2476979795053773 (hex 8cccccccccccd)
-3.5       => 3377699720527872 (hex c000000000000)
-10.0      => 1125899906842624 (hex 4000000000000)
-1234567.0 =>  798825262350336 (hex 2d68700000000)
-1e-256    => 2258570371166019 (hex 8062864ac6f43)
-1e+256    => 1495187628212028 (hex 54fdd7f73bf3c)

Mit dieser C-Referenz, die Bitfelder und eine Vereinigung verwendet, können Sie andere Zahlen überprüfen .

Beachten Sie, dass die erwartete Antwort für +nund -nfür jede Zahl gleich ist n.

Ein- und Ausgang

Es gelten Standardregeln.

Akzeptiertes Eingabeformat:

  • Eine Gleitkommazahl, die zumindest doubleintern eine Genauigkeit aufweist
  • Eine Zeichenfolgendarstellung der Zahl in Dezimalzahl (Sie müssen keine wissenschaftliche Notation unterstützen, da Sie 1000...00oder 0.0000...01als Eingabe verwenden können.)

Für die Ausgabe ist ein Rundungsfehler am niedrigstwertigen Bit tolerierbar.

Gewinnbedingung

Das ist , also gewinnt das niedrigste Byte in jeder Sprache.

Bubbler
quelle
Sandbox-Post (gelöscht)
Bubbler
1
Die Testfälle enthalten nur nicht negative Zahlen. Kann der Eingang negativ sein?
Dennis
@ Tennis Ja. Ich werde noch einige Testfälle hinzufügen.
Bubbler
3
In Ihrer Beschreibung des IEEE-Gleitkommaformats werden keine denormalen Zahlen erwähnt, die auf etwas andere Weise interpretiert werden (keine implizite führende 1). Müssen die Denormale richtig behandelt werden?
Nwellnhof
1
@nwellnhof Denormals, NaN und Infinity müssen nicht berücksichtigt werden.
Bubbler

Antworten:

8

C (gcc) , 42-30 Bytes

long f(long*p){p=*p&~0UL>>12;}

Nimmt einen Zeiger auf ein double als Argument und gibt einen long zurück .

Erfordert 64-Bit-Longs und GCC (undefiniertes Verhalten).

Danke an @nwellnhof für -2 Bytes!

Probieren Sie es online!

Dennis
quelle
&~0UL>>12ist zwei Bytes kürzer. Das Makro funktioniert jedoch nur mit lvalues.
Nwellnhof
Verwenden Sie Makro -Df(x)=*(long *)&x&~0UL>>12, speichern Sie 3 Bytes. TIO
GPS
6

Haskell, 27 31 Bytes

(`mod`2^52).abs.fst.decodeFloat

decodeFloat gibt den Signifikanden und den Exponenten zurück, aber aus irgendeinem Grund ist der erstere 53 Bit in Haskell, also müssen wir ein Bit abschneiden.

Probieren Sie es online!

nimi
quelle
5

Python 3 , 54 50 Bytes

f=lambda x:int(x.hex().split('.')[1].split('p')[0],16)

Probieren Sie es online!

Mit Kirills Vorschlag:

f=lambda x:int(x.hex()[4+(x<0):].split('p')[0],16)

Probieren Sie es online!

Luca Citi
quelle
Ich könnte mich irren, aber ich denke, Python hex()gibt normalisierte Notation, die immer mit beginnt 0x1.. Wenn ja, könnten Sie einfach nutzen diese für 44 Bytes.
Kirill L.
1
Nun, ich habe negative Zahlen vergessen, also sieht es immerhin nach 50 Bytes aus.
Kirill L.
@ kirill-l Es beginnt nicht immer mit "1". (siehe zum Beispiel (2 ** - 1028)), aber das OP sagt nichts über Subnormale aus. Ich denke, Ihr zweiter Vorschlag ist akzeptabel. Bitte zögern Sie nicht zu bearbeiten.
Luca Citi
Tatsächlich sagt das OP in einem kürzlichen Kommentar ausdrücklich, dass wir Subnormale ignorieren können.
Luca Citi
5

x86_64-Maschinensprache für Linux, 14 Byte

0:       66 48 0f 7e c0          movq   %xmm0,%rax
5:       48 c1 e0 0c             shl    $0xc,%rax
9:       48 c1 e8 0c             shr    $0xc,%rax
d:       c3                      retq

Probieren Sie es online!

Ceilingcat
quelle
Versuchen Sie, Ihren eigenen CC anstelle des Standard-ABI zu verwenden. Wenn das Double in der Rax sein muss, kannst du den gesamten Zug von xmm0 einfach fallen lassen. Hierfür ist lediglich eine Änderung erforderlich, damit das Testframework in ASM und nicht in C ausgeführt wird (es sei denn, GCC ist besonders intelligent).
Moonheart08
4

MATL , 10 Bytes

IZ%52W\0YA

Probieren Sie es online!

Erläuterung

        % Implicit input
IZ%     % Cast to uint64 without changing underlying byte representation
52W     % Push 2^52
\       % Modulus
0YA     % Convert to decimal. Gives a string. This is needed to avoid
        % the number being displayed in scientific notation
        % Implicit display
Luis Mendo
quelle
4

JavaScript (ES7), 52 bis 50 Byte

f=n=>n?n<0?f(-n):n<1?f(n*2):n<2?--n*2**52:f(n/2):0
<input oninput=o.textContent=f(this.value)><pre id=o>0

Nicht verwenden, Math.floor(Math.log2(n))da die Genauigkeit nicht garantiert wird. Bearbeiten: 2 Bytes dank @DanielIndie gespeichert.

Neil
quelle
warum nicht - n * 2 ** 52
DanielIndie
@DanielIndie Weil ich vergessen habe, dass Golf mit Schwimmern funktioniert ...
Neil
3

Perl 5 -pl , 28 Bytes

$_=-1>>12&unpack Q,pack d,$_

Probieren Sie es online!

Die Testfälle 1e-256 und 1e256 sind deaktiviert, aber das liegt daran, dass Perl 5 große oder kleine Gleitkommazeichenfolgen ungenau konvertiert.

nwellnhof
quelle
2

C (gcc) Makro, 49 Bytes

-DF(x)=x?ldexp(frexp(fabs(x),(int[1]){})-.5,53):0

Probieren Sie es online!

Gibt a zurück double jedoch eine IEEE-Genauigkeit voraus, und es wird kein Bruchteil angegeben. Behandelt jetzt auch negative Zahlen.

nwellnhof
quelle
2

T-SQL , 80 Bytes

SELECT CAST(CAST(n AS BINARY(8))AS BIGINT)&CAST(4503599627370495AS BIGINT)FROM t

Die Eingabe wird aus der Spalte neiner Tabelle mit dem Namen übernomment :

CREATE TABLE t (n FLOAT)
INSERT INTO t VALUES (0.0),(1.2),(3.1),(3.5),(10.0),(1234567.0),(1e-256),(1e+256)

SQLFiddle

Razvan Socol
quelle
2

Hoon , 25 Bytes

|*(* (mod +< (pow 2 52)))

Erstellen Sie eine generische Funktion, die den Eingabe-Mod zurückgibt 2^52 .

Nennen Sie es:

> %.  .~1e256
  |*(* (mod +< (pow 2 52)))
1.495.187.628.212.028
Rendereinstellungen
quelle
Ich hätte nie gedacht, dass ich Hoon hier sehen würde. Ich habe vor ein paar Jahren versucht, urbit zu verstehen, aber ich konnte es nicht wirklich verstehen.
rekursiver
2

JavaScript (ES7), 98 bis 76 Byte

22 (!) Bytes dank @Neil gespeichert

Ausführlicher als Neils Antwort , aber ich wollte es mit typisierten Arrays versuchen .

(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l

Probieren Sie es online!

Arnauld
quelle
ES7 + UInt32Arrayspeichert 22 Bytes:(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l
Neil
Gibt es einen Dolmetscher, der bereits implementiert hatte BigInt64Array?
tsh
0

Maschinensprache Aarch64 für Linux, 12 Byte

0:   9e660000        fmov x0, d0
4:   9240cc00        and  x0, x0, #0xfffffffffffff
8:   d65f03c0        ret

Kompilieren Sie dazu das folgende C-Programm und führen Sie es auf einem beliebigen Aarch64 Linux-Computer oder (Aarch64) Android-Gerät mit Termux aus

#include<stdio.h>
const char f[]="\0\0f\x9e\0\xcc@\x92\xc0\3_\xd6";
int main(){
  double io[] = { 0.0,
                  1.2,
                  3.1,
                  3.5,
                 10.0,
            1234567.0,
               1e-256,
               1e+256,
                 -0.0,
                 -1.2,
                 -3.1,
                 -3.5,
                -10.0,
           -1234567.0,
              -1e-256,
              -1e+256 };

  for (int i = 0; i < sizeof io / sizeof*io; i++) {
    double input = io[i];
    long output = ((long(*)(double))f)(io[i]);

    printf("%-8.7g => %16lu (hex %1$013lx)\n", input, output);
  }
}
Ceilingcat
quelle
0

Forth (gforth) , 42 Bytes

Angenommen, Floats sind standardmäßig doppelt und Zellen haben eine Länge von 8 Byte (wie auf meinem Computer und TIO).

: f f, here float - @ $fffffffffffff and ;

Probieren Sie es online!

Erläuterung

f,             \ take the top of the floating point stack and store it in memory
here float -   \ subtract the size of a float from the top of the dictionary
@              \ grab the value at the address calculated above and stick it on the stack
$fffffffffffff \ place the bitmask (equivalent to 52 1's in binary) on the stack
and            \ apply the bitmask to discard the first 12 bits

Viertens (viertens) 4-Byte- Zellenantwort , 40 Bytes

Einige ältere vierte Installationen verwenden stattdessen standardmäßig 4-Byte-Zellen

: f f, here float - 2@ swap $FFFFF and ;

Erläuterung

f,             \ take the top of the floating point stack and store it in memory
here float -   \ subtract the size of a float from the top of the dictionary
2@             \ grab the value at the address above and put it in the top two stack cells
swap           \ swap the top two cells put the number in double-cell order
$fffff         \ place the bitmask (equivalent to 20 1's in binary) on the stack
and            \ apply the bitmask to discard the first 12 bits of the higher-order cell
reffu
quelle