Kayan nokta sayısını tam olarak ondalık sayı olarak biçimlendirme


9

Herhangi bir ikili kayan nokta tam olarak ondalık olarak biçimlendirilebilir. Ortaya çıkan dize biraz uzun olabilir, ancak mümkündür. Gelen yüzen noktada yazımın ben hassasiyet önemini kapsar ve şimdi bu işlevi istiyorum. Bu zorluk, kayan nokta değerini girdi olarak alan ve kesin ondalık dizeyi çıktı olarak biçimlendiren bir program veya işlev yazmaktır.

Doğru kayan nokta sayılarıyla çalıştığımızdan emin olmak için, programa giriş olarak kesin bir format sağlanmalıdır. Bu biçim Significand Exponent, gerçek kayan nokta değerinin olduğu iki tamsayı olacaktır Significand * 2 ^ Exponent. Her iki değerin de negatif olabileceğini unutmayın.

Özellikleri:

  • En az 32 bit şamandıra aralığı ve hassasiyeti desteklenmelidir (hiçbir girdi bunun ötesine geçmeyecektir)
  • Ondalık biçimlendirilmiş değer tam bir temsil olmalıdır (şamandıraya doğru doğru bir yuvarlak uçun yeterince iyi olmadığını garanti etmek için yeterince yakın olmalıdır)
  • Standart kütüphane kayan nokta biçimlendirme işlevlerinin yeterince doğru veya yeterince hızlı (örn:) olmasına güvenmiyoruz printfve bu nedenle kullanılamayabilirler. Biçimlendirmeyi yapmanız gerekir. İntegral biçimlendirme / dönüştürme işlevlerine izin verilir.
  • .Tam sayı bileşeni yoksa önünde önde gelen sıfır hariç, önde gelen veya sondaki sıfırlar olmayabilir.
  • Bir işleve veya tüm programa izin verilir.

Örnekler:

1 -2 => 0.25
17 -3 => 2.125
-123 11 => -251904
17 50 => 19140298416324608
23 -13 => 0.0028076171875
3 120 => 3987683987354747618711421180841033728
3 -50 => 0.00000000000000266453525910037569701671600341796875
-3 -50 => -0.00000000000000266453525910037569701671600341796875
10 -2 => 2.5
-12345 -3 => -1543.125
0 0 => 0
161 -4 => 10.0625
512 -3 => 64

En kısa kod kazanır.


3
Sınırsız hassas kayan noktalı aritmetik kullanımına izin veriliyor mu?
Dennis

2
Üs negatif değilse, bununla bitebilir miyiz .0?
Sp3000

@Dennis: Evet, sınırsız veya yüksek sabit hassasiyetli aritmetiğe izin verilir.
edA-qa mort-ora-y

1
Bence bu tutarsız. Eğer baştaki 0.abcsıfır değilse, o zaman abc.0izleyen bir sıfır değildir.
orlp

1
Ayrıca .0kayan nokta sayıları ile uğraşırken her zaman tam sayılarla bitirmek için bir kongre . Bkz. Örneğin Python: str(1.0) == '1.0'versus str(1) == '1'. Mantığınız hala tutarsız.
orlp

Yanıtlar:


3

CJam, 43

r_'-&\ize999rim<s1e3'0e[W%999/(i_L?\+'.*sW%

Çevrimiçi deneyin

Açıklama:

Program, ± 999'a varan, çift hassasiyete (64 bit) yakın üslerle çalışır. Eksi işaretini (varsa) anlamlıdan ayırır, 10 999 ile çarpar, sonra şimdi tam bir hesaplama olan üsle biraz kaydırma yapar. Sonuçta 1000 basamaktan daha azsa, sola sıfırla doldurur, son 999 basamağı kesirli kısım olarak ayırır, tersini tamsayıya çevirerek sondaki sıfırları kaldırır, gerekirse bir ondalık nokta ekler ve her şeyi tekrar bir araya getirir.

r_         read and duplicate the significand in string form
'-&        keep only the minus sign, if present
\          swap with the other copy of the significand
iz         convert to integer and get absolute value
e999       multiply by 10^999
ri         read the exponent and convert to integer
m<         shift left by it; negative values will shift right
            the result is an exact non-negative integer
s          convert to string
1e3'0e[    pad to the left with zero characters up to length 1000
            longer strings will be left intact
            we need 1 more than 999 for the 0.xxx case
W%         reverse the string
999/       split into slices of length 999
(          take out the first slice (reversed fractional part)
i          convert to integer
            this removes the leading zeros (trailing in reverse)
_L?        if it's zero, replace with an empty string
\+         concatenate back (to the left) with the second slice
'.*        join the with the dot character
            if the fractional part was zero, we only have the second slice
            (reversed integer part) and there is nothing to join
s          convert to string; this is the reversed result without the sign
W%         reverse back

Sonunda, eksi işareti (varsa) ve son dize otomatik olarak birlikte yazdırılır.


2

CJam, 50 bayt

q~A1$z#\_0>K5?\z:E#@_s'-&oz*\md_sE'0e[W%isW%'.\+Q?

Bu, STDIN'den okunan tam bir programdır. CJam yorumlayıcısında çevrimiçi deneyin .

Tüm test senaryolarını bir kerede doğrulayın.


Yorumunuza dayanarak CJam'in sınırsız hassasiyete sahip olduğunu ve bunu burada kullandığınızı varsayıyorum? O zaman bu cevabın sadece 32-bit float değil, herhangi bir girişi içermesi doğru mu? Ayrıca, nasıl çalıştığına dair bir açıklama alabilir miyiz?
edA-qa mort-ora-y

CJam, tamsayılar için sınırsız bir hassasiyete sahiptir, ancak sadece çift hassas şamandıralar. Pozitif üsler için 20, negatif olanlar için 5, çarpma ipi ve nokta eklemek için 5 gücü ile çarparım. Birkaç saat içinde ayrıntılı bir açıklama ekleyeceğim.
Dennis

Ve evet, yeterli hafıza verildiğinde, bu herhangi bir girdi için işe yarayacaktır.
Dennis

10 -2, izleyen bir sıfır var gibi görünüyor
aditsu çıkıldı çünkü SE EVIL

@aditsu: Ah evet, 2'nin her gücü için bir arka sıfır ...
Dennis

2

GNU sed + dc, 65

Puan sed -rseçeneği için +1 içerir .

y/-/_/
s/.*/dc -e"C8k& 2r^*p"/e
s/\\\n//
s/0+$//
s/^(-?)\./\10./

Ben dcsadece C8k& 2r^*p10 puan için bu cevap iddia cazip oldu , ama dcbazı biçimlendirme gariplikleri vardır:

  • -ve işareti _yerine-
  • uzun çizgiler ters eğik çizgilerle kesilir
  • sondaki sıfırlar kaldırılmalıdır
  • için baştaki 0 |n| < 1eklenmelidir

Böylece dc ifadesi sedyukarıdakilere dikkat etmek için sarılır ve değerlendirilir .

Test çıktısı:

$ echo "1 -2
17 -3
-123 11
17 50
23 -13
3 120
3 -50
-3 -50
8388608 127
1 -127" | sed -rf float.sed
0.25
2.125
-251904
19140298416324608
0.0028076171875
3987683987354747618711421180841033728
0.00000000000000266453525910037569701671600341796875
-0.00000000000000266453525910037569701671600341796875
1427247692705959881058285969449495136382746624
0.0000000000000000000000000000000000000058774717541114375398436826861112283890933277838604376075437585313920862972736358642578125
$ 

Hmm, bu dctür bir biçimlendirme işlevi kullanma kuralımı ihlal ettiğini düşünüyorum .
edA-qa mort-ora-y

1
@ edA-qamort-ora-y "Sınırsız veya yüksek sabit hassasiyetli aritmetiğe izin verilir"dc verildiğinde kullanımının iyi olduğunu düşündüm . 'nin komutu bir " kayan nokta biçimlendirme işlevi" değildir - keyfi bir hassas yazdırma işlevidir. Ben herhangi bir 32bit float için fazlasıyla yeterli olduğunu düşünüyorum 128 ondalık basamak ( ), hassasiyeti ayarlıyorum . dcpC8k
Dijital Travma
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.