Çiftlerin Üssü


12

Arka fon

IEEE 754 Çift kesinlikli kayar nokta biçimi , 64 bitlik gerçek sayıları temsil etmenin bir yoludur. Aşağıdaki gibi görünüyor:

Gerçek sayı aşağıdaki şekilde ndönüştürülür double:

  1. sSayı pozitifse işaret biti 0, aksi takdirde 1'dir.
  2. Mutlak değeri nformda 2**y * 1.xxx, yani bir bazın 2 katı güç olarak temsil edilir .
  3. Üs eolan y(2 gücü) eksi 1023.
  4. Kesir f, xxxen önemli 52 biti alan kısımdır (tabanın kesirli kısmı).

Tersine, bir bit deseni (işaret s, üs eve kesirle tanımlanır f, her biri bir tam sayı) sayıyı temsil eder:

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

Meydan okuma

Gerçek sayısı göz önüne alındığında n, çıkışının 52 bit fraksiyon kısmı, doubletemsili nbir tam sayı olarak.

Test Durumları

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)

Bit alanlarını ve bir birleşimi kullanan bu C başvurusunu kullanarak diğer numaraları kontrol edebilirsiniz .

Beklenen cevabın herhangi bir sayı için +nve -nherhangi bir sayı için aynı olduğunu unutmayın n.

Giriş ve çıkış

Standart kurallar geçerlidir.

Kabul edilen giriş biçimi:

  • En az doubledahili hassasiyete sahip bir kayan noktalı sayı
  • Sayının ondalık olarak dize ile temsil edilmesi (bilimsel gösterimi desteklemenize gerek yoktur, çünkü giriş 1000...00veya 0.0000...01giriş olarak kullanabilirsiniz )

Çıktı için, en az anlamlı bitte bir yuvarlama hatası tolere edilebilir.

Kazanma Koşulu

Bu , bu nedenle her dilde en düşük bayt kazanır.



1
Test senaryoları yalnızca negatif olmayan sayıları içerir. Girdi negatif olabilir mi?
Dennis

@Dennis Evet. Biraz daha test örneği ekleyeceğim.
Bubbler

3
IEEE kayan nokta biçimi tanımınız, biraz farklı bir şekilde yorumlanan denormal sayılardan bahsetmez (örtük satır 1 yoktur). Denormaller doğru kullanılmalı mı?
nwellnhof

1
@nwellnhof Denormalleri, NaN ve Infinity'yi düşünmenize gerek yoktur.
Bubbler

Yanıtlar:


8

C (gcc) , 42 30 bayt

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

Alır bir işaretçi çift argüman olarak ve bir döner uzun .

64 bit uzunluğunda ve gcc (tanımlanmamış davranış) gerektirir.

@ Bynhof'a -2 bayt için teşekkürler!

Çevrimiçi deneyin!


&~0UL>>12iki bayt daha kısadır. Ancak makro yalnızca değerlerle çalışır.
nwellnhof

Makro kullanın -Df(x)=*(long *)&x&~0UL>>12, 3 bayt kaydedin. TIO
GPS

6

Haskell, 27 31 bayt

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

decodeFloatönemini ve üssünü döndürür, ancak bir nedenle Haskell'de eski 53 bittir , bu yüzden bir bit kesmeliyiz.

Çevrimiçi deneyin!


5

Python 3 , 54 50 bayt

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

Çevrimiçi deneyin!

Kirill'in önerisiyle:

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

Çevrimiçi deneyin!


Yanılıyor olabilirim, ama bence Python'un hex()her zaman başlayan normalleştirilmiş gösterimi var 0x1.. Eğer öyleyse, sadece kullanabilirsiniz bu 44 byte için.
Kirill L.

1
Negatif sayıları unuttum, bu yüzden sonuçta 50 bayt gibi görünüyor .
Kirill L.

@ kirill-l Her zaman "1" ile başlamaz. (örneğin bkz. (2 ** - 1028)) ancak OP alt normaller hakkında bir şey söylemez, bu yüzden sanırım ikinci öneriniz kabul edilebilir. Lütfen düzenlemekten çekinmeyin.
Luca Citi

Aslında son zamanlarda yapılan bir yorumda OP açıkça alt normalleri göz ardı edebileceğimizi söylüyor.
Luca Citi

5

Linux için x86_64 makine dili, 14 bayt

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

Çevrimiçi deneyin!


standart ABI yerine kendi CC'nizi kullanmayı deneyin. Çiftin raxta olmasını gerektirerek, tüm hareketi xmm0'dan kolayca bırakabilirsiniz. Bunun için gereken değişiklik, test çerçevesini C yerine ASM'de yapmaktır (GCC çok akıllı olmadığı sürece).
moonheart08

4

MATL , 10 bayt

IZ%52W\0YA

Çevrimiçi deneyin!

açıklama

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

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))Doğru olmadığı garanti edilmediğinden kullanılmıyor . Düzenleme: @DanielIndie sayesinde 2 bayt kaydedildi.


neden olmasın --n * 2 ** 52
DanielIndie

@DanielIndie Çünkü o golf yüzen ile çalışır unuttum ...
Neil

3

Perl 5 -pl , 28 bayt

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

Çevrimiçi deneyin!

1e-256 ve 1e256 test senaryoları kapalı ancak Perl 5'in büyük veya küçük kayan nokta dizelerini tam olarak dönüştürmemesi nedeniyle.


2

C (gcc) makro, 49 bayt

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

Çevrimiçi deneyin!

İade bir doubleama IEEE hassas varsayarak, bir kesirli kısmını olmayacaktır. Artık negatif sayıları da ele alıyor.


2

T-SQL , 80 bayt

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

Girdi şu ntablonun sütunundan alınır 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 bayt

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

Giriş modunu döndüren genel bir işlev oluşturun 2^52.

Aramak:

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

Burada hoon göreceğimi hiç düşünmemiştim. Birkaç yıl önce urbit'i anlamaya çalıştım, ama gerçekten kafalarını ya da kuyruklarını yapamadım.
özyinelemeli

2

JavaScript (ES7), 98 76 bayt

@Neil sayesinde 22 (!) Bayt kaydedildi

Neil'in cevabından daha ayrıntılı , ama yazılan dizilerle denemek istedim .

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

Çevrimiçi deneyin!


ES7 + UInt32Array22 bayt kaydeder:(n,[l,h]=new Uint32Array(new Float64Array([n]).buffer))=>(h&-1>>>12)*2**32+l
Neil

BigInt64ArrayHalihazırda uygulanmış bir tercüman var mı ?
tsh


1

Stax , 19 14 bayt

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

Çalıştır ve hata ayıkla

Paketten çıkarılmış, çözülmemiş ve yorum yapılmıştır, kod şöyle görünür.

|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

Bunu çalıştır





0

Linux için Aarch64 makine dili, 12 bayt

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

Bunu denemek için, herhangi bir Aarch64 Linux makinesinde veya Termux çalıştıran (Aarch64) Android cihazında aşağıdaki C programını derleyin ve çalıştırın

#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

İleri (gforth) , 42 bayt

Yüzenlerin varsayılan olarak iki katına çıktığını ve hücrelerin 8 bayt uzunluğunda olduğunu varsayıyorum (bilgisayarımda ve TIO'da olduğu gibi)

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

Çevrimiçi deneyin!

açıklama

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

Dördüncü (gforth) 4 bayt hücre yanıtı, 40 bayt

Bazı eski ileri kurulumlar varsayılan olarak 4 bayt hücrelere ayarlanır

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

açıklama

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.