A Base do Duplo


12

fundo

O formato de ponto flutuante de precisão dupla IEEE 754 é uma maneira de representar números reais com 64 bits. Parece o seguinte:

Um número real né convertido doubleem da da seguinte maneira:

  1. O bit do sinal sé 0 se o número for positivo, 1 caso contrário.
  2. O valor absoluto de né representado na forma 2**y * 1.xxx, ou seja, uma potência de 2 vezes a base .
  3. O expoente eé y(a potência de 2) menos 1023.
  4. A fração fé a xxxparte (parte fracionária da base), levando os 52 bits mais significativos.

Por outro lado, um padrão de bits (definido por sinal s, expoente ee fração f, cada um inteiro) representa o número:

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

Desafio

Dado um número real n, imprima sua parte da fração de 52 bits da doublerepresentação ncomo um número inteiro.

Casos de teste

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)

Você pode verificar outros números usando esta referência C, que usa campos de bits e uma união.

Observe que a resposta esperada é a mesma para +ne -npara qualquer número n.

Entrada e saída

Aplicam-se regras padrão.

Formato de entrada aceito:

  • Um número de ponto flutuante, pelo menos com doubleprecisão internamente
  • Uma representação em seqüência do número em decimal (você não precisa suportar notação científica, pois pode usar 1000...00ou 0.0000...01como entrada)

Para saída, um erro de arredondamento no bit menos significativo é tolerável.

Condição vencedora

Isso é , então os bytes mais baixos em cada idioma vencem.



1
Os casos de teste incluem apenas números não negativos. A entrada pode ser negativa?
— Dennis

@Dennis Sim. Vou adicionar mais alguns casos de teste.
— Bubbler

3
Sua descrição do formato de ponto flutuante IEEE não menciona números desnormais que são interpretados de uma maneira ligeiramente diferente (sem avanço implícito 1). Os denormais precisam ser manuseados corretamente?
— Nwellnhof 31/03/19

1
@nwellnhof Você não precisa considerar denormals, NaN e Infinity.
— Bubbler 31/03

Respostas:



6

Haskell, 27 31 bytes

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

decodeFloatretorna o significando e o expoente, mas, por alguma razão, o primeiro está com 53 bits em Haskell, então precisamos cortar um pouco.

Experimente online!


5

Python 3 , 54 50 bytes

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

Experimente online!

Com a sugestão de Kirill:

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

Experimente online!


Posso estar errado, mas acho que o Python hex()fornece uma notação normalizada que sempre começa com 0x1.. Nesse caso, você pode usar isso por 44 bytes.
— 31518 Kirill L.Mar

1
Bem, eu esqueci números negativos, então parece 50 bytes afinal.
— Kirill L.

@ kirill-l Nem sempre começa com "1". (veja por exemplo (2 ** - 1028)), mas o OP não diz nada sobre subnormais, então acho que sua segunda sugestão é aceitável. Sinta-se livre para editar.
— Luca Citi

Na verdade, em um comentário recente, o OP diz explicitamente que podemos ignorar com segurança subnormais.
— Luca Citi

5

Linguagem de máquina x86_64 para Linux, 14 bytes

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

Experimente online!


tente usar seu próprio CC em vez da ABI padrão. Ao exigir o duplo estar em rax, você pode facilmente remover todo o movimento de xmm0. Somente a mudança necessária para isso é tornar a estrutura de teste no ASM, e não no C (a menos que o GCC seja extremamente inteligente).
— usar o seguinte código

4

MATL , 10 bytes

IZ%52W\0YA

Experimente online!

Explicação

        % 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

4

JavaScript (ES7), 52 50 bytes

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

Não usar Math.floor(Math.log2(n))porque não é garantido que seja preciso. Editar: salvou 2 bytes graças a @DanielIndie.


por que não -N * 2 ** 52
— DanielIndie

@DanielIndie Porque eu esqueci que que o golfe funciona com flutuadores ...
— Neil

3

Perl 5 -pl , 28 bytes

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

Experimente online!

Os casos de teste 1e-256 e 1e256 estão desativados, mas isso ocorre porque o Perl 5 converte inexatamente cadeias enormes ou minúsculas de ponto flutuante.


2

Macro C (gcc) , 49 bytes

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

Experimente online!

Retorna uma, doublemas assumindo precisão IEEE, ela não terá uma parte fracionária. Também lida com números negativos agora.


2

T-SQL , 80 bytes

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

A entrada é obtida da coluna nde uma tabela denominada 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


2

Hoon , 25 bytes

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

Crie uma função genérica que retorne o mod de entrada 2^52.

Chamando:

> %.  .~1e256
  |*(* (mod +< (pow 2 52)))
1.495.187.628.212.028

Eu nunca pensei que veria hoon aqui. Tentei entender o urbit há alguns anos, mas não conseguia entender direito.
— recursivo

2

JavaScript (ES7), 98 76 bytes

Economizou 22 (!) Bytes graças a @Neil

Mais detalhado que a resposta de Neil , mas eu queria tentar com matrizes digitadas .

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

Experimente online!


O ES7 + UInt32Arraysalva 22 bytes:(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l
— Neil

Existe algum intérprete que BigInt64Arrayjá tenha implementado ?
— Tsh


1

Stax , 19 14 bytes

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

Execute e depure

Descompactado, não jogado e comentado, o código fica assim.

|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

Execute este





0

Linguagem de máquina Aarch64 para Linux, 12 bytes

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

Para tentar isso, compile e execute o seguinte programa C em qualquer máquina Aarch64 Linux ou dispositivo (Aarch64) Android executando o 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);
  }
}


0

Quarto (gforth) , 42 bytes

Supõe que os flutuadores tenham o dobro por padrão e as células tenham 8 bytes de comprimento (como é o caso no meu computador e no TIO)

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

Experimente online!

Explicação

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

Quarta (gforth) resposta de célula de 4 bytes, 40 bytes

Algumas instalações mais antigas são padronizadas para células de 4 bytes,

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

Explicação

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.