双打基地


12

背景

IEEE 754双精度浮点格式是一种表示64位实数的方法。看起来如下:

实数按以下方式n转换为double

  1. s如果数字为正,则符号位为0,否则为1。
  2. 的绝对值n22**y * 1.xxx乘以base的形式表示。
  3. 指数ey(2的幂)减去1023。
  4. 分数fxxx部分(基数的分数部分),采用最高有效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参考来检查其他数字,该C参考使用位字段和联合。

需要注意的是预期的答案是一样的+n,并-n为任意数量n

输入输出

适用标准规则。

接受的输入格式:

  • 浮点数,double内部至少具有精度
  • 以十进制表示的数字的字符串表示形式(您无需支持科学计数法,因为您可以使用1000...000.0000...01作为输入)

对于输出,最低有效位的舍入误差是可以容忍的。

获奖条件

这是,因此每种语言中的最低字节为准。


沙盒帖子(已删除)
Bubbler'Mar

1
测试用例仅包含非负数。输入可以为负吗?
丹尼斯

@丹尼斯是的。我将添加更多测试用例。
Bubbler '18

3
您对IEEE浮点格式的描述未提及非正常数字,该非正常数字的解释方式略有不同(没有隐式前导1)。异常情况必须正确处理吗?
nwellnhof '18

1
@nwellnhof您不需要考虑异常,NaN和Infinity。
Bubbler '18

Answers:



6

Haskell,27 31字节

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

decodeFloat返回有效位数和指数,但由于某种原因,前者在Haskell中为53位,因此我们必须将其舍去一位。

在线尝试!


5

Python 3中54 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个字节。
基里尔

1
好吧,我忘记了负数,所以看起来毕竟是50个字节
基里尔·L.18年

@ kirill-l并非总是以“ 1”开头。(例如,请参阅(2 **-1028)),但OP并未对次正规化发表任何评论,因此我认为您的第二个建议是可以接受的。请随时进行编辑。
卡·花旗

实际上,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

在线尝试!


尝试使用自己的CC代替标准的ABI。通过要求double在rax中,您可以轻松地从xmm0删除整个动作。唯一需要做的更改就是在ASM而不是C中创建测试框架(除非GCC更加智能)。
moonheart08年

4

MATL,10字节

IZ%52W\0YA

在线尝试!

说明

        % 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字节

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

我从没想过我会在这里看到白痴。几年前,我曾尝试了解urbit,但并不能真正做到这一点。
递归

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


1

Stax19 14 字节

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

运行并调试

解压,解压和注释,代码看起来像这样。

|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

运行这个





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

第四(gforth),42字节

假设默认情况下,浮点数是双精度的,单元格的长度是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

第四(gforth) 4字节单元格答案,40字节

某些较旧的第四安装默认为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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.