油嘴滑舌:g_ascii_dtostr 不精确?
我对一些 glib 函数(例如“g_ascii_dtostr”)(以及使用双精度的 GKeyFile 函数)的工作方式有点感兴趣。
考虑这一行:
gchar buf[30];
g_message("Double: %f, as String: %s", 0.2, g_ascii_dtostr(buf, 30, 0.2));
哪个输出
Double: 0.200000, as String: 0.20000000000000001
(只有当我将缓冲区大小设置得足够高时才会发生奇怪的转换)
当我(例如)将双“1.9”存储在 GKeyFile 中时会发生类似的事情,但在生成的文件中它被保存为“1.8999999999999999”。 显然,通过“g_ascii_strtod”返回的转换应该是无损的,但它仍然困扰着我为什么会首先发生这种奇怪的情况。这也使我的配置键值文件变得非常难看。
我想我已经在某处读到过使用中间“long double”类型,但这仍然无法澄清为什么转换后的值是“脏”的,因为例如我认为从 int 到 double 的转换没有任何类似的效果。
I am a little bit intrigued by the way some glib functions such as "g_ascii_dtostr" (and the GKeyFile functions using doubles) work.
Consider this line:
gchar buf[30];
g_message("Double: %f, as String: %s", 0.2, g_ascii_dtostr(buf, 30, 0.2));
Which outputs
Double: 0.200000, as String: 0.20000000000000001
(The weird conversion only happens when I set the buffer size high enough though)
Similar things happen when I (for example) store the double "1.9" in a GKeyFile, but in the resulting file it is saved as "1.8999999999999999".
Apparently the conversion back through "g_ascii_strtod" is supposed to be lossless, but it still bothers me why this weirdness happens in the first place. Also this makes my config key-value files pretty ugly..
I think I have read somewhere once that an intermediate "long double" type is used, but this still wouldn't clarify why the converted value is "dirty", because e.g. a conversion from int to double for doesn't have any similar effects I think.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自文档:
“该函数生成足够的精度,使用 g_ascii_strtod() 将字符串转换回相同的机器编号(在具有 IEEE 兼容 64 位双精度数的机器上)。”
正如 caf 在他的评论中指出的那样, %f 说明符在六位十进制数字后截断,因此 g_ascii_strtod() 为您提供更准确的值。如果您想要此截断,可以使用 g_ascii_formatd()。
From the documentation:
"This functions generates enough precision that converting the string back using g_ascii_strtod() gives the same machine-number (on machines with IEEE compatible 64bit doubles)."
As caf noted in his comment, the %f specifier truncates after six decimal digits, so g_ascii_strtod() gives you the more accurate value. You can use g_ascii_formatd() if you want this truncation.