Cơ sở đôi


12

Lý lịch

Định dạng dấu phẩy động chính xác kép của IEEE 754 là cách biểu diễn các số thực với 64 bit. Nó trông giống như sau:

Một số thực nđược chuyển đổi thành một doubletheo cách sau:

  1. Bit dấu slà 0 nếu số dương, 1 nếu không.
  2. Giá trị tuyệt đối của nđược biểu diễn dưới dạng 2**y * 1.xxx, tức là sức mạnh gấp 2 lần một cơ sở .
  3. Số mũ ey( lũy thừa của 2) trừ 1023.
  4. Phân số fxxxphần (phần phân đoạn của cơ sở), lấy 52 bit đáng kể nhất.

Ngược lại, một mẫu bit (được xác định bằng dấu s, số mũ evà phân số f, mỗi số nguyên) đại diện cho số:

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

Thử thách

Cho một số thực n, xuất ra phần phân số 52 bit của doublebiểu diễn ndưới dạng một số nguyên.

Các trường hợp thử nghiệm

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)

Bạn có thể kiểm tra các số khác bằng cách sử dụng tham chiếu C này sử dụng các trường bit và liên kết.

Lưu ý rằng câu trả lời dự kiến ​​là giống nhau cho +n-ncho bất kỳ số nào n.

Đầu vào và đầu ra

Quy tắc chuẩn áp dụng.

Định dạng đầu vào được chấp nhận:

  • Một số dấu phẩy động, ít nhất là có doubleđộ chính xác trong nội bộ
  • Một chuỗi đại diện cho số ở dạng thập phân (bạn không cần hỗ trợ ký hiệu khoa học, vì bạn có thể sử dụng 1000...00hoặc 0.0000...01làm đầu vào)

Đối với đầu ra, một lỗi làm tròn ở bit quan trọng nhất có thể chấp nhận được.

Điều kiện chiến thắng

Đây là , vì vậy các byte thấp nhất trong mỗi ngôn ngữ sẽ thắng.



1
Các trường hợp thử nghiệm chỉ bao gồm các số không âm. Đầu vào có thể là âm?
Dennis

@Dennis Có. Tôi sẽ thêm một số trường hợp thử nghiệm.
Bong bóng

3
Mô tả của bạn về định dạng dấu phẩy động của IEEE không đề cập đến các số bất thường được diễn giải theo một cách hơi khác (không dẫn đầu ẩn 1). Làm biến dạng phải được xử lý chính xác?
nwellnhof

1
@nwellnhof Bạn không cần phải xem xét các biến dạng, NaN và Infinity.
Bong bóng

Câu trả lời:



6

Haskell, 27 31 byte

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

decodeFloattrả về giá trị và số mũ, nhưng vì một số lý do trước đây là 53 bit trong Haskell, vì vậy chúng tôi phải cắt bỏ một bit.

Hãy thử trực tuyến!


5

Python 3 , 54 50 byte

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

Hãy thử trực tuyến!

Với đề nghị của Kirill:

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

Hãy thử trực tuyến!


Tôi có thể sai, nhưng tôi nghĩ rằng Python hex()đưa ra ký hiệu chuẩn hóa luôn bắt đầu bằng 0x1.. Nếu vậy, bạn chỉ có thể sử dụng điều này cho 44 byte.
Kirill L.

1
Chà, tôi đã quên mất các số âm, vì vậy nó trông giống như 50 byte .
Kirill L.

@ kirill-l Không phải lúc nào cũng bắt đầu bằng "1." (xem ví dụ (2 ** - 1028)) nhưng OP không nói gì về subnormals, vì vậy tôi đoán đề xuất thứ hai của bạn có thể chấp nhận được. Xin vui lòng chỉnh sửa.
Luca Citi

Trên thực tế trong một bình luận gần đây, OP nói rõ rằng chúng ta có thể bỏ qua các subnorm một cách an toàn.
Luca Citi

5

Ngôn ngữ máy x86_64 cho Linux, 14 byte

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

Hãy thử trực tuyến!


thử và sử dụng CC của riêng bạn thay vì ABI tiêu chuẩn. Bằng cách yêu cầu nhân đôi thành rax, bạn có thể dễ dàng thả toàn bộ di chuyển từ xmm0. Chỉ thay đổi cần thiết cho việc này là tạo khung thử nghiệm trong ASM chứ không phải C (Trừ khi GCC là thông minh hơn).
moonheart08

4

MATL , 10 byte

IZ%52W\0YA

Hãy thử trực tuyến!

Giải trình

        % 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 byte

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

Không sử dụng Math.floor(Math.log2(n)) vì nó không được đảm bảo là chính xác. Chỉnh sửa: Đã lưu 2 byte nhờ @DanielIndie.


tại sao không --n * 2 ** 52
DanielẤn

@DanielIndie Bởi vì tôi quên rằng golf hoạt động với phao ...
Neil

3

Perl 5 -pl , 28 byte

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

Hãy thử trực tuyến!

Các trường hợp thử nghiệm 1e-256 và 1e256 đã tắt nhưng đó là do Perl 5 chuyển đổi các chuỗi dấu phẩy động lớn hoặc nhỏ một cách không chính xác.


2

Macro C (gcc) , 49 byte

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

Hãy thử trực tuyến!

Trả về doublenhưng giả sử độ chính xác của IEEE, nó sẽ không có phần phân đoạn. Cũng xử lý số âm bây giờ.


2

T-SQL , 80 byte

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

Đầu vào được lấy từ cột ncủa bảng có 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 byte

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

Tạo một hàm chung trả về mod đầu vào 2^52 .

Gọi nó là:

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

Tôi không bao giờ nghĩ rằng tôi sẽ thấy hoon ở đây. Tôi đã cố gắng để hiểu được urbit một vài năm trước đây, nhưng thực sự không thể tạo ra đầu hay đuôi của nó.
đệ quy



1

Stax , 19 14 byte

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

Chạy và gỡ lỗi nó

Giải nén, không ghi chú và nhận xét, mã trông như thế này.

|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

Chạy cái này





0

Ngôn ngữ máy Aarch64 cho Linux, 12 byte

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

Để dùng thử, hãy biên dịch và chạy chương trình C sau trên bất kỳ máy Aarch64 Linux hoặc (Aarch64) thiết bị Android nào chạy 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

Forth (gforth) , 42 byte

Giả sử số float là gấp đôi theo mặc định và các ô có độ dài 8 byte (như trường hợp trên máy tính của tôi và TIO)

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

Hãy thử trực tuyến!

Giải trình

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)Câu trả lời ô 4 byte , 40 byte

Thay vào đó, một số cài đặt cũ hơn mặc định cho các ô 4 byte, thay vào đó

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

Giải trình

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.