【问题标题】:Truncate f-string float without rounding截断 f 字符串浮点数而不四舍五入
【发布时间】:2020-06-17 16:00:22
【问题描述】:

我想打印一个非常接近一的浮点数,将其截断到小数点后 2 位而不进行四舍五入,最好使用尽可能少的代码。

a = 0.99999999999
print(f'{a:0.2f}')
Expected: 0.99
Actual: 1.00

【问题讨论】:

  • 乘以100,调用math.floor(),然后除以100。
  • @Barmar 也许trunc 而不是floor 让它也适用于负数? (不相关,如果已知输入接近 1 并因此为正)
  • 对于数字“非常接近一”,乘以 100 会产生舍入,可能形成乘积 == 100.0。相反,将舍入模式设置为 0,然后打印到小数点后 17 位以上,并在 . 之后删除除 2 位以外的所有数字。

标签: python floating-point decimal f-string


【解决方案1】:

如果我理解正确的话,我认为你不需要 f 字符串或数学函数。简单的旧字符串操作应该可以帮助您:

a = 0.987654321
print(str(a)[:4])

输出:

0.98

【讨论】:

  • 0.99999999999999988897769753748434595763683319091796875 失败。然后str(a) 产生“1.0”。
  • @EricPostpischil - 不,它没有。刚刚试了一下。
  • 它可能取决于 Python 版本和/或实现。
  • @EricPostpischil 不这么认为;一个字符串是一个字符串,并且该字符串的[4] 索引位置中的字符就是这样。不执行舍入函数。
  • 0.9899999999999999911182158029987476766109466552734375 是一个在当前常见的 Python 实现中失败的示例。这个值在常用的 IEEE-754 binary64 中是可以表示的,但是 Python 的str 可能会为其生成“0.99”,然后问题中的代码错误地显示“0.99”而不是“0.98”。 (注意,与您断言不执行舍入相反,它实际上是舍入,因为在您的示例中传递给它的实际浮点值不是 0.987654321 而是 0.987654320999999994619565768516622483730316162109375。)
【解决方案2】:

在 python 方面不够熟练,但这里的浮点数学肯定与 C 足够接近——我精通。

Python 的 float 和 C 的 double 一样是以 2 为底数,所以像 0.xx 这样的值,除了 0.00, 0.25, 0.50, 0.75 之外,不能被精确编码。

让我们试试a=0.87。最接近的可表示 pythonfloat 值是:

 # 1234567890123456789012  
 0.8699999999999999955591...

所以真实值小于0.87。

打印少于 18 位的数字(str() 显然是这样)会导致输出向上取整。

 # 12345678901234567
 0.87000000000000000

并且在文本上截断导致"0.87",并且不满足“将其截断到小数点后2位而不四舍五入”,因为原始值为0.8699999999999999955591...

要解决此问题,代码需要在调用str() 之前更改float 数学的舍入模式以向0 舍入而不是舍入到最接近的值 转换为具有额外精度的字符串。我怀疑 python 可以做到这一点 - 我不知道。

即使有更高的精度(仍然使用四舍五入),在一般情况下,仍然可能存在真值为 xxx.xx(许多 9 的)的情况......这会四舍五入并阻止我们的文本截断。

【讨论】:

  • Re “我怀疑 python 可以做到这一点 - 我不知道。”:Python 允许请求具有很高精度的格式(如 %.99g % x`),一些实现可能正确地做到这一点.但是 Python 对浮点数很松懈。 documentation 不包含关于其特征或行为的强烈声明。未指定是否正确实现了多位字符串的转换,因此不能依赖。而且我认为 Python 没有控制舍入模式的规定。
  • 基本上,如果你想要可靠的浮点运算,Python 不是一种可以使用的语言。
  • @EricPostpischil 感谢 python 输入。如果没有控制舍入模式的规定,这项任务很难处理好所有情况。回复:“是否正确实现了多个数字到字符串的转换”,也是一个编码漏洞。我希望 python 能够朝着正确的float 方向发展,以使用至少 20 位的 IEEE 754 规范进行字符串处理。
猜你喜欢
  • 2011-12-27
  • 2011-05-10
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多