当前位置: 首页 > 面试题库 >

浮点数和字符串转换的奇怪行为

云德辉
2023-03-14
问题内容

我已经将其输入python shell:

>>> 0.1*0.1
0.010000000000000002

我期望0.1 * 0.1不是0.01,因为我知道以10为底的0.1是周期性的,以2为底。

>>> len(str(0.1*0.1))
4

我已经看过20个以上的字符,因此我希望能得到20个。为什么我得到4?

>>> str(0.1*0.1)
'0.01'

好吧,这解释了为什么我len给了我4,但为什么str回归'0.01'

>>> repr(0.1*0.1)
'0.010000000000000002'

为什么不str回合repr?(我已经阅读了这个答案,但是我想知道他们如何决定何时str对浮点数进行取整,以及何时对不进行浮点取整)

>>> str(0.01) == str(0.0100000000001)
False
>>> str(0.01) == str(0.01000000000001)
True

因此,浮子的准确性似乎是一个问题。我以为Python会使用IEEE 754单精度浮点数。所以我已经检查过了:

#include <stdint.h>
#include <stdio.h> // printf

union myUnion {
    uint32_t i; // unsigned integer 32-bit type (on every machine)
    float f;    // a type you want to play with
};

int main() {
    union myUnion testVar;
    testVar.f = 0.01000000000001f;
    printf("%f\n", testVar.f);

    testVar.f = 0.01000000000000002f;
    printf("%f\n", testVar.f);

    testVar.f = 0.01f*0.01f;
    printf("%f\n", testVar.f);
}

我有:

0.010000
0.010000
0.000100

Python给了我:

>>> 0.01000000000001
0.010000000000009999
>>> 0.01000000000000002
0.010000000000000019
>>> 0.01*0.01
0.0001

Python为什么会给我这些结果?

(我使用的是Python 2.6.5。如果您知道Python版本之间的差异,我也会对此感兴趣。)


问题答案:

关键的要求repr是它应该往返。也就是说,在所有情况下eval(repr(f)) == f都应给予True

在Python
2.x(2.7之前的版本)中,它repr通过printf对format进行格式化%.17g并舍弃尾随零来工作。IEEE-754保证这是正确的(对于64位浮点数)。从2.7和3.1开始,Python使用了一种更智能的算法,该算法可以在某些情况下找到较短的表示形式,%.17g从而给出不必要的非零终端数字或终端数字9。请参阅3.1的新功能?并发行1580。

即使在Python 2.7下,也会repr(0.1 * 0.1)给出"0.010000000000000002"。这是因为0.1 * 0.1 == 0.01False在IEEE-754解析和算法;
也就是说,与之最接近的64位浮点值与0.1自身相乘时,将得出一个64位的浮点值,该值不是与之最接近的64位浮点值0.01

>>> 0.1.hex()
'0x1.999999999999ap-4'
>>> (0.1 * 0.1).hex()
'0x1.47ae147ae147cp-7'
>>> 0.01.hex()
'0x1.47ae147ae147bp-7'
                 ^ 1 ulp difference

repr和之间str(2.7 /
3.1之前的版本)的区别在于,str格式具有12位小数而不是17位,这是不可四舍五入的,但是在许多情况下产生的可读性更高。



 类似资料:
  • 问题内容: 正如标题所说。我不认为有可能这样做,但如果可以告诉我。 这是我正在编写的bukkit(minecraft服务器)插件所必需的。我要执行一个命令:tnt [power]。电源是我想转换为浮点数的返回字符串。 谢谢 问题答案: 用于进行转换。 和之间的区别只是回报。如果需要(对象),请使用前者;如果要数字,请使用后者。

  • 问题内容: http://golang.org/pkg/strconv/ http://play.golang.org/p/4VNRgW8WoB 如何将浮点数转换为字符串格式?这是google游乐场,但未获得预期的输出。(2e + 07)我想得到“ 21312421.213123” 请帮助我从浮点数中获取字符串。谢谢 问题答案: 试试这个 如果只想获得尽可能高的位数精度,则特殊精度-1使用所需的最

  • 问题内容: 我有一些奇怪的字符串池行为的问题。我正在使用比较相等的字符串来找出它们是否在池中。 输出为: 这对我来说是一个很大的惊喜。有人可以解释一下吗?我认为这是在编译时发生的。但是,为什么添加到String 根本没有任何区别呢? 问题答案: 是一个编译时常量,而 不是。因此,前者仅编译为字符串常量“ 555”,而后者则编译为实际的方法调用和串联,从而生成一个新的String实例。 另请参见JL

  • 我正在使用一个groovy脚本将正文中的一些值转换为它们的原始数据类型。为了实现这一点,我使用了JsonSluper和JsonOutput。JsonSluper和JsonOutput正在将字符串中的一些符号从json主体转换为奇怪的字符。有什么建议可以解决这个问题吗? 示例:“UnitPrice”:“99美分/磅”转换为“UnitPrice”::“99\u00a2每磅” 已转换为 我的脚本: 下面

  • 问题内容: 这是我正在查看的内容: 因此,我知道不能完全用二进制表示“ p” 1.15的十进制值。 因此,大的十进制大“ bdp”输出对我来说非常有意义……这是浮点数的实际值。 问题1 当浮点数“ p”转换回字符串以进行输出(如1.15)时,如何四舍五入(从内部1.149..375到1.15)? 在文档中的什么地方指定?toString javadoc并没有真正帮助(至少对我来说)。 我在语言规范

  • 我看到的是: 所以我知道“p”1.15的十进制值不能用二进制来精确表示。 所以大的十进制“bdp”输出对我来说非常有意义……这是浮点数的实际值。 问题 1 当浮点数“p”转换回字符串以进行输出(如 1.15)时,该舍入如何/在何处发生(从内部 1.149..375 值转换为 1.15)? 它在文档中的哪个位置指定?托斯特林爪哇并没有真正的帮助(至少我)。 我确实在语言规范中看到了这一点: 浮点和双