ฐานของคู่


12

พื้นหลัง

IEEE 754 รูปแบบจุดลอยตัวความแม่นยำสองเท่าเป็นวิธีการแสดงตัวเลขจริงด้วย 64 บิต ดูเหมือนว่าต่อไปนี้:

จำนวนจริงnจะถูกแปลงเป็น a doubleในลักษณะดังต่อไปนี้:

  1. เครื่องหมายบิตsคือ 0 ถ้าตัวเลขเป็นบวกหรือ 1 มิฉะนั้น
  2. ค่าสัมบูรณ์ของnมีตัวแทนอยู่ในรูปแบบ2**y * 1.xxxกล่าวคืออำนาจของ 2ครั้งฐาน
  3. เลขชี้กำลังeคือy(กำลัง 2) ลบ 1023
  4. เศษส่วนfคือxxxส่วน (ส่วนที่เป็นเศษส่วนของฐาน) ซึ่งมีค่า 52 บิตที่สำคัญที่สุด

ในทางกลับกันรูปแบบบิต (กำหนดโดยเครื่องหมายsเลขชี้กำลังeและเศษส่วนfแต่ละจำนวนเต็ม) แทนจำนวน:

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

ท้าทาย

ให้จำนวนจริงnเอาท์พุทส่วนเศษ 52- บิตของการdoubleเป็นตัวแทนของ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และตัวเลขใด-nn

อินพุตและเอาต์พุต

ใช้กฎมาตรฐาน

รูปแบบอินพุตที่ยอมรับ:

  • ตัวเลข floating-point อย่างน้อยก็มีdoubleความแม่นยำภายใน
  • การแสดงสตริงของตัวเลขเป็นทศนิยม (คุณไม่จำเป็นต้องสนับสนุนสัญลักษณ์ทางวิทยาศาสตร์เนื่องจากคุณสามารถใช้1000...00หรือ0.0000...01เป็นอินพุต)

สำหรับเอาต์พุตข้อผิดพลาดในการปัดเศษที่บิตที่มีนัยสำคัญน้อยที่สุดจะยอมรับได้

สภาพการชนะ

นี่คือดังนั้นไบต์ต่ำสุดในแต่ละภาษาชนะ


โพสต์ Sandbox (ถูกลบ)
Bubbler

1
กรณีทดสอบประกอบด้วยเฉพาะตัวเลขที่ไม่เป็นลบ อินพุตสามารถเป็นลบได้หรือไม่?
Dennis

@Dennis ใช่ ฉันจะเพิ่มอีกกรณีทดสอบ
Bubbler

3
คำอธิบายของคุณเกี่ยวกับรูปแบบทศนิยมของ IEEE ไม่ได้หมายถึงตัวเลขที่ผิดปกติซึ่งจะตีความในลักษณะที่แตกต่างกันเล็กน้อย (ไม่มีการนำหน้าโดยนัย 1) ต้องจัดการ denormals อย่างถูกต้องหรือไม่?
nwellnhof

1
@nwellnhof คุณไม่จำเป็นต้องพิจารณาเรื่อง denormals, NaN และ Infinity
Bubbler

คำตอบ:


8

C (GCC) , 42 30 ไบต์

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

ใช้เวลาชี้ไปที่คู่เป็นอาร์กิวเมนต์และผลตอบแทนระยะยาว

ต้องการความยาว 64- บิตและ gcc (ลักษณะการทำงานที่ไม่ได้กำหนด)

ขอบคุณ @nwellnhof สำหรับ -2 ไบต์!

ลองออนไลน์!


&~0UL>>12สั้นกว่าสองไบต์ แม้ว่าแมโครจะใช้งานได้กับ lvalues ​​เท่านั้น
nwellnhof

ใช้มาโคร-Df(x)=*(long *)&x&~0UL>>12บันทึก 3 ไบต์ TIO
GPS

6

Haskell, 27 31 ไบต์

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

decodeFloatส่งคืนค่าซิกนิฟิแคนด์และเลขชี้กำลัง แต่ด้วยเหตุผลบางอย่างค่าเดิมคือ53 บิตใน Haskell ดังนั้นเราต้องตัดหนึ่งบิต

ลองออนไลน์!


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 ไบต์
Kirill L.

1
ฉันลืมตัวเลขลบดังนั้นดูเหมือน50 ไบต์หลังจากทั้งหมด
Kirill L.

@ kirill-l มันไม่ได้ขึ้นต้นด้วย "1. " เสมอไป (ดูตัวอย่าง (2 ** - 1,028)) แต่ OP ไม่ได้พูดอะไรเกี่ยวกับ subnormals ดังนั้นฉันเดาว่าคำแนะนำที่สองของคุณเป็นที่ยอมรับ โปรดแก้ไข
Luca Citi

ที่จริงแล้วในความคิดเห็นเมื่อเร็ว ๆ นี้ OP บอกอย่างชัดเจนว่าเราสามารถเพิกเฉย subnormals ได้อย่างปลอดภัย
Luca Citi

5

x86_64 ภาษาเครื่องสำหรับ Linux, 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

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))เนื่องจากไม่รับประกันว่าจะถูกต้อง แก้ไข: บันทึก 2 ไบต์ขอบคุณ @DanielIndie


ทำไมไม่ --n * 2 ** 52
DanielIndie

@DanielIndie เพราะฉันลืมไปว่ากอล์ฟนั้นใช้งานได้กับ ...
Neil

3

Perl 5 -pl , 28 ไบต์

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

ลองออนไลน์!

เคสทดสอบ 1e-256 และ 1e256 ปิดอยู่ แต่นั่นเป็นเพราะ Perl 5 แปลงสตริงจุดลอยตัวขนาดใหญ่หรือเล็กอย่างไม่แน่นอน


2

มาโครC (gcc) 49 ไบต์

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

ลองออนไลน์!

ส่งคืนdoubleแต่ความแม่นยำของ IEEE สมมติว่าไม่มีส่วนที่เป็นเศษส่วน จัดการตัวเลขลบตอนนี้ด้วย


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

ฮุน 25 ไบต์

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

สร้างฟังก์ชั่นทั่วไปที่ส่งกลับ 2^52mod

เรียกมันว่า:

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

ฉันไม่เคยคิดว่าฉันจะเห็นฮุนอยู่ที่นี่ ฉันพยายามที่จะเข้าใจเพิ่มขึ้นอีกสองสามปีก่อน แต่ไม่สามารถทำให้หัวหรือก้อยได้
เรียกซ้ำ

2

JavaScript (ES7), 98 76 ไบต์

ไบต์ที่บันทึก 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
Neil

มีล่ามคนใดบ้างที่นำBigInt64Arrayไปใช้งานแล้ว?
tsh


1

Stax , 19 14 ไบต์

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

เรียกใช้และแก้ไขข้อบกพร่อง

คลายไฟล์ ungolfed และแสดงความคิดเห็นโค้ดมีลักษณะเช่นนี้

|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

ภาษาเครื่อง Aarch64 สำหรับ Linux ขนาด 12 ไบต์

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

เพื่อลองใช้งานให้รวบรวมและรันโปรแกรม C ต่อไปนี้บนเครื่อง Aarch64 Linux หรืออุปกรณ์ Android (Aarch64) ที่รัน 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

มา (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

Forth (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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.