请问 Python 如何强制不使用科学计数法打印浮点数?

2022-04-04 05:26:34 +08:00
 Richard14

有如下数据

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

全部不满足需求。浮点数输出一个人类友好的写法有什么优雅的写法吗?目前能想到的唯一达成目标输出的方法只有将输出结果作为字符串处理,感觉很肮脏。

4624 次点击
所在节点    Python
13 条回复
muzuiget
2022-04-04 06:09:28 +08:00
十进制"字面量"被解析过后,就变成二进制,已经丢失了精度,所以你怎么整也还原不了十进制。

你要用 decimal 库,全程用字符串表示和运算,Python 会用更多的内存来记录一个数字。
Richard14
2022-04-04 06:27:34 +08:00
@muzuiget 我觉得既然 float(y)可以输出 1e-16 ,那么自然就保留了足够的信息输出 0.0000000000000001 ,毕竟两者可以一一映射,3.3333333333333333e-21 和 0.000000000000000000003333333333333333 同理
renmu123
2022-04-04 06:37:45 +08:00
科学计数法不比数数字友好?
kilasuelika
2022-04-04 08:09:15 +08:00
这个只能自己实现一个。
不是所有十进制小数都能用浮点精确表示的,会有一个 round off 。那么必然存在这样一种情况:有多个相近的十进制小数,它们的浮点表示是相同的。
那么拿到一个浮点表示,其实是没法反推输入的十进制数。

如果自己实现的话,可以对浮点数 round 一下,比如查小数部分开头有多少个 0 ,就按这个 round 。
hsfzxjy
2022-04-04 11:11:14 +08:00
用 g 啊

'{:g}'.format(y)
Richard14
2022-04-04 11:54:47 +08:00
@hsfzxjy 我在 3.8 的输出结果是 1e-16?
Richard14
2022-04-04 11:59:20 +08:00
@kilasuelika 反推的话,问题在于这是 python ,浮点数内存模型不是 f64 ,print(.000000000000000000000000000000001)的结果是 1e-33 ,print(.0000000000000000000000000000000012)的结果是 1.2e-33 ,我觉得起码在题目描述的场景中不存在“多个相近的十进制小数的浮点数表示相同”这句话


@renmu123 如果一定无法解决需求的话,解决提出需求的人也许也是不错的办法
hsfzxjy
2022-04-04 14:10:12 +08:00
@Richard14 抱歉看错了,我以为你要"智能"的表示,比如自动科学计数法
rudy1224
2022-04-04 15:29:47 +08:00
不要从 float 转 decimal

<script src="https://gist.github.com/huidididi/5eb8a628cdec07e05bd5b7ccf404241d.js"></script>
kilasuelika
2022-04-04 16:13:06 +08:00
@Richard14 十进制下有限位数的小数,转换成二进制可以是无限长度的,但计算机不可能存储无限长度的二进制。所以肯定存在者不同的十进制小数,它们的二进制存储是一样的,这跟有没有用 IEEE 浮点数没有关系。
不信你可以试一下:
```
0.00010000000000000000000000000000000000000000000001==0.0001
```
python 中结果是 True 。
kilasuelika
2022-04-04 16:14:40 +08:00
@Richard14 直接 print 的时候,用的科学计数法,自动有 round 的效果,所以才会显示等于 1e-33 ,但实际的二进制表示并不等于十进制的 1e-33 。
Richard14
2022-04-05 02:05:06 +08:00
@kilasuelika 谢谢你的回复,但这里需要解决实际问题,我知道你举例情况的存在,但我在上面楼层已强调我的需求场景。并且我觉得你比起回复应该多做些功课,不要回出“自动有 round 效果”这种莫名其妙的。。
threebr
2022-04-05 05:28:37 +08:00
假设你需要 4 位有效数字
a = '{:.'+str(3-int(math.log10(y)))+'f}'
print(a.format(y))

0.0000000000000001000

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/844824

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX