La base du double

12

Contexte

IEEE 754 Le format à virgule flottante double précision est un moyen de représenter des nombres réels avec 64 bits. Il ressemble à ceci:

Un nombre réel nest converti en a doublede la manière suivante:

  1. Le bit de signe sest 0 si le nombre est positif, 1 sinon.
  2. La valeur absolue de nest représentée sous la forme 2**y * 1.xxx, c'est -à- dire une puissance de 2 fois une base .
  3. L'exposant eest y(la puissance de 2) moins 1023.
  4. La fraction fest la xxxpartie (partie fractionnaire de la base), prenant les 52 bits les plus significatifs.

Inversement, un motif binaire (défini par signe s, exposant eet fraction f, chacun un entier) représente le nombre:

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

Défi

Étant donné un nombre réel n, affichez sa partie de fraction de 52 bits de la doublereprésentation nsous forme d'entier.

Cas de test

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)

Vous pouvez vérifier d'autres nombres en utilisant cette référence C qui utilise des champs de bits et une union.

Notez que la réponse attendue est la même pour +net -npour n'importe quel nombre n.

Entrée et sortie

Des règles standard s'appliquent.

Format d'entrée accepté:

  • Un nombre à virgule flottante, ayant au moins une doubleprécision interne
  • Une représentation sous forme de chaîne du nombre en décimal (vous n'avez pas besoin de prendre en charge la notation scientifique, car vous pouvez utiliser 1000...00ou 0.0000...01en entrée)

Pour la sortie, une erreur d'arrondi au bit le moins significatif est tolérable.

Condition gagnante

Il s'agit de , donc les octets les plus bas dans chaque langue gagnent.

Bubbler
la source
Publication
1
Les cas de test incluent uniquement des nombres non négatifs. L'entrée peut-elle être négative?
Dennis
@Dennis Oui. Je vais ajouter quelques cas de test supplémentaires.
Bubbler
3
Votre description du format à virgule flottante IEEE ne mentionne pas les nombres dénormaux qui sont interprétés de manière légèrement différente (pas de début implicite 1). Les dénormals doivent-ils être traités correctement?
nwellnhof
1
@nwellnhof Vous n'avez pas besoin de considérer les dénormals, NaN et Infinity.
Bubbler

Réponses:

8

C (gcc) , 42 30 octets

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

Prend un pointeur sur un double comme argument et renvoie un long .

Requiert 64 bits longs et gcc (comportement non défini).

Merci à @nwellnhof pour -2 octets!

Essayez-le en ligne!

Dennis
la source
&~0UL>>12est de deux octets plus court. Cependant, la macro ne fonctionne qu'avec lvalues.
nwellnhof
Utilisez une macro -Df(x)=*(long *)&x&~0UL>>12, économisez 3 octets. TIO
GPS
6

Haskell, 27 31 octets

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

decodeFloatrenvoie la signification et l'exposant, mais pour une raison quelconque, le premier est de 53 bits dans Haskell, nous devons donc couper un bit.

Essayez-le en ligne!

nimi
la source
5

Python 3 , 54 50 octets

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

Essayez-le en ligne!

Avec la suggestion de Kirill:

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

Essayez-le en ligne!

Luca Citi
la source
Je peux me tromper, mais je pense que Python hex()donne une notation normalisée qui commence toujours par 0x1.. Si oui, vous pouvez simplement utiliser ce pour 44 octets.
Kirill L.
1
Eh bien, j'ai oublié les nombres négatifs, donc ça ressemble à 50 octets après tout.
Kirill L.
@ kirill-l Ça ne commence pas toujours par "1." (voir par exemple (2 ** - 1028)) mais l'OP ne dit rien sur les sous-normales, donc je suppose que votre deuxième suggestion est acceptable. N'hésitez pas à modifier.
Luca Citi
En fait, dans un récent commentaire, l'OP dit explicitement que nous pouvons ignorer les sous-normales en toute sécurité.
Luca Citi
5

Langage machine x86_64 pour Linux, 14 octets

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

Essayez-le en ligne!

plafond
la source
essayez d'utiliser votre propre CC au lieu de l'ABI standard. En exigeant que le double soit en rax, vous pouvez facilement supprimer le mouvement entier de xmm0. Le seul changement nécessaire pour cela est de rendre le framework de test dans ASM plutôt qu'en C (sauf si GCC est extra intelligent).
moonheart08
4

MATL , 10 octets

IZ%52W\0YA

Essayez-le en ligne!

Explication

        % 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
la source
4

JavaScript (ES7), 52 50 octets

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

Ne pas utiliser Math.floor(Math.log2(n))car il n'est pas garanti d'être précis. Edit: sauvé 2 octets grâce à @DanielIndie.

Neil
la source
pourquoi pas --n * 2 ** 52
DanielIndie
@DanielIndie Parce que j'ai oublié que le golf fonctionne avec des flotteurs ...
Neil
3

Perl 5 -pl , 28 octets

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

Essayez-le en ligne!

Les cas de test 1e-256 et 1e256 sont désactivés, mais c'est parce que Perl 5 convertit inexactement des chaînes de virgule flottante énormes ou minuscules.

nwellnhof
la source
2

Macro C (gcc) , 49 octets

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

Essayez-le en ligne!

Renvoie un doublemais en supposant une précision IEEE, il n'aura pas de partie fractionnaire. Gère également les nombres négatifs maintenant.

nwellnhof
la source
2

T-SQL , 80 octets

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

L'entrée provient de la colonne nd'une table nommée t:

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
la source
2

Hoon , 25 octets

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

Créez une fonction générique qui renvoie le mod d'entrée 2^52.

L'appeler:

> %.  .~1e256
  |*(* (mod +< (pow 2 52)))
1.495.187.628.212.028
RenderSettings
la source
Je n'ai jamais pensé voir hoon ici. J'ai essayé de comprendre Urbit il y a quelques années, mais je ne pouvais pas vraiment en faire la tête ou la queue.
récursif
2

JavaScript (ES7), 98 76 octets

22 (!) Octets enregistrés grâce à @Neil

Plus verbeux que la réponse de Neil , mais je voulais l'essayer avec des tableaux typés .

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

Essayez-le en ligne!

Arnauld
la source
ES7 + UInt32Arrayenregistre 22 octets:(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l
Neil
Y a-t-il un interprète qui avait BigInt64Arraydéjà mis en place ?
tsh
1

Stax , 19 14 octets

üâïc-Hò~÷]ó┬ó♪

Exécuter et déboguer

Décompressé, non golfé et commenté, le code ressemble à ceci.

|a      absolute value
{HcDw   double until there's no fractional part
@       convert to integer type
:B      convert to binary digits
D52(    drop the first digit, then pad to 52
:b      convert back number

Exécutez celui-ci

récursif
la source
0

Langage machine Aarch64 pour Linux, 12 octets

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

Pour l'essayer, compilez et exécutez le programme C suivant sur n'importe quelle machine Linux Aarch64 ou appareil Android (Aarch64) exécutant Termux

#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);
  }
}
plafond
la source
0

Forth (gforth) , 42 octets

Suppose que les flotteurs sont doubles par défaut et que les cellules ont une longueur de 8 octets (comme c'est le cas sur mon ordinateur et TIO)

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

Essayez-le en ligne!

Explication

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

Forth (gforth) réponse de cellule de 4 octets, 40 octets

Certaines anciennes installations en avant par défaut à des cellules de 4 octets, à la place

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

Explication

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