V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Richard14
V2EX  ›  Python

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

  •  
  •   Richard14 · 2022-04-04 05:26:34 +08:00 · 5014 次点击
    这是一个创建于 998 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有如下数据

    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
    

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

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

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

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

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


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

    <script src="https://gist.github.com/huidididi/5eb8a628cdec07e05bd5b7ccf404241d.js"></script>
    kilasuelika
        10
    kilasuelika  
       2022-04-04 16:13:06 +08:00   ❤️ 1
    @Richard14 十进制下有限位数的小数,转换成二进制可以是无限长度的,但计算机不可能存储无限长度的二进制。所以肯定存在者不同的十进制小数,它们的二进制存储是一样的,这跟有没有用 IEEE 浮点数没有关系。
    不信你可以试一下:
    ```
    0.00010000000000000000000000000000000000000000000001==0.0001
    ```
    python 中结果是 True 。
    kilasuelika
        11
    kilasuelika  
       2022-04-04 16:14:40 +08:00
    @Richard14 直接 print 的时候,用的科学计数法,自动有 round 的效果,所以才会显示等于 1e-33 ,但实际的二进制表示并不等于十进制的 1e-33 。
    Richard14
        12
    Richard14  
    OP
       2022-04-05 02:05:06 +08:00
    @kilasuelika 谢谢你的回复,但这里需要解决实际问题,我知道你举例情况的存在,但我在上面楼层已强调我的需求场景。并且我觉得你比起回复应该多做些功课,不要回出“自动有 round 效果”这种莫名其妙的。。
    threebr
        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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1422 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:58 · PVG 07:58 · LAX 15:58 · JFK 18:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.