ダブルのベース


12

バックグラウンド

IEEE 754倍精度浮動小数点形式は、64ビットで実数を表現する方法です。次のようになります。

実数ndouble、次の方法でa に変換されます。

  1. s数値が正の場合、符号ビットは0、それ以外の場合は1です。
  2. の絶対値はnの形式2**y * 1.xxxで表されます。つまり、baseの2のべき乗倍です。
  3. 指数ey(2 のべき乗)-1023です。
  4. 画分がfあるxxx最も重要な52ビットを取る部分(基部の小数部分)。

逆に、ビットパターン(sign s、exponent eおよびfraction fで定義され、それぞれ整数)は数値を表します。

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

チャレンジ

実数を指定するnと、のdouble表現の52ビットの小数部をn整数として出力します。

テストケース

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)

ビットフィールドとユニオンを使用するこのCリファレンスを使用して他の数値を確認できます。

予想される答えはで同じであることに注意+nして-n、任意の数のためにn

入出力

標準ルールが適用されます。

使用可能な入力形式:

  • 少なくともdouble内部的に精度を持つ浮動小数点数
  • 10進数の文字列表現(1000...00または0.0000...01を使用できるため、科学表記法をサポートする必要はありません)

出力の場合、最下位ビットでの丸め誤差は許容範囲です。

勝利条件

これはであるため、各言語の最下位バイトが優先されます。



1
テストケースには、負でない数のみが含まれます。入力は負の値にできますか?
デニス

@デニスはい。さらにテストケースを追加します。
バブラー

3
IEEE浮動小数点形式の説明では、わずかに異なる方法で解釈される非正規数について言及していません(暗黙の先行1はありません)。デノーマルは正しく処理する必要がありますか?
-nwellnhof

1
@nwellnhofデノーマル、NaN、Infinityを考慮する必要はありません。
バブラー

回答:


8

C(gcc)42 30バイト

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

引数としてdoubleへのポインターを取りlongを返します。

64ビットのlongとgcc(未定義の動作)が必要です。

-2バイトの@nwellnhofに感謝します!

オンラインでお試しください!


&~0UL>>122バイト短くなります。ただし、マクロは左辺値でのみ機能します。
-nwellnhof

マクロを使用して-Df(x)=*(long *)&x&~0UL>>12、3バイトを節約します。TIO
GPS


5

Pythonの354の 50バイト

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

オンラインでお試しください!

キリルの提案:

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

オンラインでお試しください!


私は間違っているかもしれませんが、Pythonのhex()正規化された表記は常にで始まると思います0x1.。その場合は、これを44バイトで使用できます。
キリルL.

1
負の数を忘れてしまったので、結局50バイトのように見えます
キリルL.

@ kirill-l常に「1」で始まるとは限りません。(たとえば(2 **-1028)を参照)しかし、OPはサブノーマルについて何も言わないので、2番目の提案は受け入れられると思います。編集してください。
ルカシティ

実際に、最近のコメントでは、OPは非正規数を安全に無視できると明示的に述べています。
ルカシティ

5

Linux用のx86_64マシン言語、14バイト

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

オンラインでお試しください!


標準のABIの代わりに独自のCCを使用してみてください。ダブルがraxにあることを要求することにより、xmm0から移動全体を簡単にドロップできます。これに必要な変更は、CではなくASMでテストフレームワークを作成することだけです(GCCが特別に賢明でない限り)。
moonheart08


4

JavaScript(ES7)、52 50バイト

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

Math.floor(Math.log2(n))正確性が保証されていないため、使用していません。編集:@DanielIndieのおかげで2バイトを保存しました。


なぜ--n * 2 ** 52
DanielIndie

@DanielIndieゴルフがフロートで機能することを忘れていたからです...-
ニール



2

T-SQL、80バイト

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

入力はn、という名前のテーブルの列から取得されます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バイト

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

入力modを返す汎用関数を作成します2^52

それを呼び出す:

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

私はここでフンを見るとは思わなかった。私は数年前にアービットを理解しようとしましたが、それを実際に理解することはできませんでした。
再帰的

2

JavaScript(ES7)、98 76バイト

@Neilのおかげで22(!)バイト節約

Neilの答えよりも冗長ですが、型付き配列を試してみたかったのです。

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

オンラインでお試しください!


ES7 + UInt32Arrayは22バイトを節約します:(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l
ニール

BigInt64Array既に実装されているインタープリターはありますか?
tsh






0

Linux用Aarch64マシン言語、12バイト

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

これを試すには、Termuxを実行しているAarch64 Linuxマシンまたは(Aarch64)Androidデバイスで次のCプログラムをコンパイルして実行します

#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

Forth(gforth)、42バイト

デフォルトではフロートが2倍で、セルの長さは8バイトであると想定しています(コンピューターとTIOの場合)

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

オンラインでお試しください!

説明

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) 4バイトのセル応答、40バイト

いくつかの古い4番目のインストールでは、代わりに4バイトのセルがデフォルトになります

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

説明

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.