有如下数据
x: float = .00000000000000000001 / 3
y: float = .0000000000000001
想要实现的输出结果:
>>> print(some_func(x))
0.000000000000000000003333333333333333
>>> print(some_func(y))
0.0000000000000001
当前输出结果:
>>> print(y)
1e-16
>>> print('%f' % y)
0.000000
>>> print('{.50f}'.format(y))
0.00000000000000009999999999999999790977867240346036
>>> print(Decimal(y))
9.999999999999999790977867240346035618411149408467364363417573258630000054836273193359375E-17
全部不满足需求。浮点数输出一个人类友好的写法有什么优雅的写法吗?目前能想到的唯一达成目标输出的方法只有将输出结果作为字符串处理,感觉很肮脏。
1
muzuiget 2022-04-04 06:09:28 +08:00
十进制"字面量"被解析过后,就变成二进制,已经丢失了精度,所以你怎么整也还原不了十进制。
你要用 decimal 库,全程用字符串表示和运算,Python 会用更多的内存来记录一个数字。 |
2
Richard14 OP @muzuiget 我觉得既然 float(y)可以输出 1e-16 ,那么自然就保留了足够的信息输出 0.0000000000000001 ,毕竟两者可以一一映射,3.3333333333333333e-21 和 0.000000000000000000003333333333333333 同理
|
3
renmu123 2022-04-04 06:37:45 +08:00 via Android
科学计数法不比数数字友好?
|
4
kilasuelika 2022-04-04 08:09:15 +08:00 via Android
这个只能自己实现一个。
不是所有十进制小数都能用浮点精确表示的,会有一个 round off 。那么必然存在这样一种情况:有多个相近的十进制小数,它们的浮点表示是相同的。 那么拿到一个浮点表示,其实是没法反推输入的十进制数。 如果自己实现的话,可以对浮点数 round 一下,比如查小数部分开头有多少个 0 ,就按这个 round 。 |
5
hsfzxjy 2022-04-04 11:11:14 +08:00 via Android
用 g 啊
'{:g}'.format(y) |
7
Richard14 OP @kilasuelika 反推的话,问题在于这是 python ,浮点数内存模型不是 f64 ,print(.000000000000000000000000000000001)的结果是 1e-33 ,print(.0000000000000000000000000000000012)的结果是 1.2e-33 ,我觉得起码在题目描述的场景中不存在“多个相近的十进制小数的浮点数表示相同”这句话
@renmu123 如果一定无法解决需求的话,解决提出需求的人也许也是不错的办法 |
9
rudy1224 2022-04-04 15:29:47 +08:00
不要从 float 转 decimal
<script src="https://gist.github.com/huidididi/5eb8a628cdec07e05bd5b7ccf404241d.js"></script> |
10
kilasuelika 2022-04-04 16:13:06 +08:00 1
@Richard14 十进制下有限位数的小数,转换成二进制可以是无限长度的,但计算机不可能存储无限长度的二进制。所以肯定存在者不同的十进制小数,它们的二进制存储是一样的,这跟有没有用 IEEE 浮点数没有关系。
不信你可以试一下: ``` 0.00010000000000000000000000000000000000000000000001==0.0001 ``` python 中结果是 True 。 |
11
kilasuelika 2022-04-04 16:14:40 +08:00
@Richard14 直接 print 的时候,用的科学计数法,自动有 round 的效果,所以才会显示等于 1e-33 ,但实际的二进制表示并不等于十进制的 1e-33 。
|
12
Richard14 OP @kilasuelika 谢谢你的回复,但这里需要解决实际问题,我知道你举例情况的存在,但我在上面楼层已强调我的需求场景。并且我觉得你比起回复应该多做些功课,不要回出“自动有 round 效果”这种莫名其妙的。。
|
13
threebr 2022-04-05 05:28:37 +08:00
假设你需要 4 位有效数字
a = '{:.'+str(3-int(math.log10(y)))+'f}' print(a.format(y)) 0.0000000000000001000 |