格式化浮点数与十进制完全相同


9

任何二进制浮点都可以完全以十进制格式设置。结果字符串可能有些长,但是有可能。在关于浮点的文章中,我谈到了精度的重要性,现在我需要此功能。面临的挑战是编写一个程序或函数,该程序或函数将浮点值作为输入并格式化精确的十进制字符串作为输出。

为了确保我们使用正确的浮点数,必须提供精确的格式作为程序的输入。此格式将是两个整数Significand Exponent,实际的浮点值是Significand * 2 ^ Exponent。请注意,两个值都可以为负。

细节:

  • 必须支持至少32位浮点数的范围和精度(没有输入会超出该范围)
  • 十进制格式的值必须是精确的表示形式(仅足够接近以保证正确的倒圆角浮点不够好)
  • 我们不信任标准库浮点格式化功能足够正确或不够快(例如:)printf,因此可能无法使用它们。必须进行格式化。允许使用集成格式/转换功能。
  • 可能没有任何前导零或尾随零,除非在.没有整数部分的情况下,前面必须有一个前导零。
  • 允许一个功能或整个程序。

例子:

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

最短的代码胜出。


3
是否可以使用无限精度的浮点运算?
丹尼斯

2
如果指数为非负数,我们可以以.0?结尾吗?
Sp3000

@丹尼斯:是的,允许无限制或高精度的算术运算。
edA-qa mort-ora-y

1
我认为这是不一致的。如果0.abc不是前导零,则abc.0不是尾随的。
orlp

1
约定.0在处理浮点数时总是以整数结尾。例如,参见Python:str(1.0) == '1.0'vs str(1) == '1'。您的逻辑仍然不一致。
orlp

Answers:


3

CJam,43岁

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

在线尝试

说明:

该程序可使用高达±999的指数,接近双精度(64位)。它将负号(如果存在)与有效数分开,将其乘以10 999,然后对指数进行一点位移,这现在是精确的计算。然后,如果结果少于1000个数字,则用零向左填充,将最后999个数字分隔为小数部分,通过将其反向转换为整数来删除尾随的零,如果需要则添加小数点,然后将所有内容放在一起。

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

最后,减号(如果有的话)和最后的字符串会自动一起打印。


2

CJam,50个字节

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

这是一个从STDIN读取的完整程序。在CJam解释器中在线尝试。

一次验证所有测试用例。


根据您的评论,我认为CJam具有无限的精度,您在这里使用过吗?那么,此答案涵盖任何输入,而不仅仅是32位浮点数,是否正确?另外,我们可以对其工作原理进行解释吗?
edA-qa mort-ora-y

CJam具有无限精度的整数,但只有双精度浮点数。我将正指数乘以20的幂,将负指数乘以5的幂,强制转换为字符串并插入点。我将在几个小时内添加详细的说明。
丹尼斯

是的,给定足够的内存,这应该适用于任何输入。
丹尼斯

10 -2似乎有尾随零
aditsu退出,因为SE恶

@aditsu:是的,每2的幂次幂后跟一个零...
Dennis

2

GNU sed + dc,65

分数包括sed -r选项的+1 。

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

我很想提出这个dc仅回答C8k& 2r^*p10分的答案,但是dc有一些格式方面的怪癖:

  • -ve符号_代替-
  • 长行用反斜杠断开
  • 尾随零必须删除
  • |n| < 1必须添加前导0

因此,dc表达式会被包装并规避,sed以照顾上述情况。

测试输出:

$ 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
$ 

嗯,我认为dc这种违反我使用标准格式设置功能的规则。
edA-qa mort-ora-y

1
@ edA-qamort-ora-y我认为使用dc可以,因为“允许无限或高精度的算术运算”dcp命令不是“ 浮点格式设置功能”,而是任意精度的打印功能。我将精度设置为128个小数位(C8k),我认为对于任何32位浮点数来说,这已经足够了。
Digital Trauma 2015年
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.