2013年12月11日 星期三 18:40
Hello all, 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: 92542.2817 如果我把它作为浮点数存储到C++变量中,如: double number = 92542.2817; 则不管是使用stringstream把它转换为字符串,还是在调试器里面 看这个变量赋值后的值,都是: 92542.28170000001 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 问题了? 求指教? 多谢! B.R Kermit
2013年12月12日 星期四 02:13
https://en.wikipedia.org/wiki/IEEE_floating_point Float 是有误差的。 可以看一下 http://www.boost.org/doc/libs/1_54_0/libs/math/doc/html/math_toolkit/high_precision.html 如果你可以使用 boost -- Difan Zhang (@tifan) http://tifan.net/ 2013/12/11 Kermit.Mei <kermit.mei at gmail.com> > Hello all, > > 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: > 92542.2817 > > 如果我把它作为浮点数存储到C++变量中,如: > double number = 92542.2817; > > 则不管是使用stringstream把它转换为字符串,还是在调试器里面 > 看这个变量赋值后的值,都是: > > 92542.28170000001 > > 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 > > 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 > 问题了? > > > 求指教? 多谢! > > B.R > Kermit > _______________________________________________ > zeuux-universe mailing list > zeuux-universe at zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://www.zeuux.org/pipermail/zeuux-universe/attachments/20131211/4c2a4de4/attachment.html>
2013年12月12日 星期四 10:23
感谢各位的回复! 用boost和GMP的大数库应该才是最终的解决之道,但我没时间移植了, 只能连夜写个自己的Double类型,原理是用 long long 存储和计算数据, 必要时转换为string显示。 long long在我的机器上是64位,可获取18位的精度,先不考虑效率,顶 一阵子先吧,嘿嘿。 Thanks B.R Kermit > 在 2013年12月12日,上午2:13,Alex Zhang <cheungtifan在gmail.com> 写道: > > https://en.wikipedia.org/wiki/IEEE_floating_point > > Float 是有误差的。 > > 可以看一下 http://www.boost.org/doc/libs/1_54_0/libs/math/doc/html/math_toolkit/high_precision.html 如果你可以使用 boost > > > > -- > Difan Zhang (@tifan) > http://tifan.net/ > > > 2013/12/11 Kermit.Mei <kermit.mei在gmail.com> >> Hello all, >> >> 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: >> 92542.2817 >> >> 如果我把它作为浮点数存储到C++变量中,如: >> double number = 92542.2817; >> >> 则不管是使用stringstream把它转换为字符串,还是在调试器里面 >> 看这个变量赋值后的值,都是: >> >> 92542.28170000001 >> >> 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 >> >> 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 >> 问题了? >> >> >> 求指教? 多谢! >> >> B.R >> Kermit >> _______________________________________________ >> zeuux-universe mailing list >> zeuux-universe在zeuux.org >> http://www.zeuux.org/mailman/listinfo/zeuux-universe >> >> ZEUUX Project - Free Software, Free Society! >> http://www.zeuux.org > > _______________________________________________ > zeuux-universe mailing list > zeuux-universe在zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org -------------- 下一部分 -------------- 一个HTML附件被移除... URL: <http://www.zeuux.org/pipermail/zeuux-universe/attachments/20131212/1318ca5b/attachment-0001.html>
2013年12月18日 星期三 16:05
double 是使用二进制存储的。 所有的十进制有限位整数都可以无误差转换成二进制有限位整数。 但十进制有限位小数无法转化为二进制有限位小数。如果一个十进制小数对应一个无限位二进制小数,则该小数使用 double 保存会造成误差。通过这一点可以让你发现产生误差的规律。 比较明确的说: 925422817 这样的整数,使用 double 保存绝对不会有误差。 0.5,0.25,0.125,0.0625,0.03125,0.015625 等等这样的 0.5 的幂次,使用 double 保存不会有误差。 使用上述数据一次加成的,不会有误差。 例如 0.625 = 0.5+0.125 ,这个数使用 double 保存不会有误差 例如 99999.5625 = 99999 + 0.5 +0.0625 ,这个数使用 double 保存不会有误差 无法通过上述方法分解的小数,使用 double 保存,都会发生误差。 以上规律告诉你了什么数保存会发生误差。至于怎么使用看自己了。如果你只需要保存不需要计算的话,可以直接将这个数保存为 925422817 这种整数,注意整数就算保存在 double 类型里面也不会有误差。 2013/12/11 Kermit.Mei <kermit.mei在gmail.com> > Hello all, > > 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: > 92542.2817 > > 如果我把它作为浮点数存储到C++变量中,如: > double number = 92542.2817; > > 则不管是使用stringstream把它转换为字符串,还是在调试器里面 > 看这个变量赋值后的值,都是: > > 92542.28170000001 > > 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 > > 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 > 问题了? > > > 求指教? 多谢! > > B.R > Kermit > _______________________________________________ > zeuux-universe mailing list > zeuux-universe在zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org -------------- 下一部分 -------------- 一个HTML附件被移除... URL: <http://www.zeuux.org/pipermail/zeuux-universe/attachments/20131218/a6099cae/attachment.html>
2013年12月23日 星期一 12:08
感谢pansz兄的指点,抱歉,我一直在想您给的这个规律怎么用,所以现在才回复。 很遗憾最后我还是没能想到一个算法,用这个"0.5次幂规律"来检测我的double是否 有误差。最后,我想了一个十分简单的解决方案: 把结果double转换成字符串,检验字符串中小数点后的11位(因为我迄今见过的最大 的误差就在这位上),然后从第11位开始做一次四舍五入。把结果最后的 '0' 去掉,如 过最后的字符串长度比传入的长度小 5, 那么我就认为它做了校验误差的操作,比如: "92542.28170000001" 对字符串 小数点后第11位"四舍五入" "92542.2817" 对比字符串长度,发现长度相差 5,就认为剔除误差了。 不过最后再顺便问一句:按照下面那个 0.5幂次的规律,我能否得出这个结论: double保存的数如果存在误差,那么这个误差数小数最后一位只可能是:1, 5, 9 三者之一? 如果能得出这个结论,那么我就可以用这种字符串过滤方法算得更 精确一步。 Thanks B.R Kermit > 在 18 Dec 2013,16:05,pansz <pan.shizhu在gmail.com> 写道: > > double 是使用二进制存储的。 > > 所有的十进制有限位整数都可以无误差转换成二进制有限位整数。 > > 但十进制有限位小数无法转化为二进制有限位小数。如果一个十进制小数对应一个无限位二进制小数,则该小数使用 double 保存会造成误差。通过这一点可以让你发现产生误差的规律。 > > 比较明确的说: > 925422817 这样的整数,使用 double 保存绝对不会有误差。 > 0.5,0.25,0.125,0.0625,0.03125,0.015625 等等这样的 0.5 的幂次,使用 double 保存不会有误差。 > 使用上述数据一次加成的,不会有误差。 > 例如 0.625 = 0.5+0.125 ,这个数使用 double 保存不会有误差 > 例如 99999.5625 = 99999 + 0.5 +0.0625 ,这个数使用 double 保存不会有误差 > > 无法通过上述方法分解的小数,使用 double 保存,都会发生误差。 > > 以上规律告诉你了什么数保存会发生误差。至于怎么使用看自己了。如果你只需要保存不需要计算的话,可以直接将这个数保存为 925422817 这种整数,注意整数就算保存在 double 类型里面也不会有误差。 > > > > 2013/12/11 Kermit.Mei <kermit.mei在gmail.com> >> Hello all, >> >> 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: >> 92542.2817 >> >> 如果我把它作为浮点数存储到C++变量中,如: >> double number = 92542.2817; >> >> 则不管是使用stringstream把它转换为字符串,还是在调试器里面 >> 看这个变量赋值后的值,都是: >> >> 92542.28170000001 >> >> 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 >> >> 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 >> 问题了? >> >> >> 求指教? 多谢! >> >> B.R >> Kermit >> _______________________________________________ >> zeuux-universe mailing list >> zeuux-universe在zeuux.org >> http://www.zeuux.org/mailman/listinfo/zeuux-universe >> >> ZEUUX Project - Free Software, Free Society! >> http://www.zeuux.org > > _______________________________________________ > zeuux-universe mailing list > zeuux-universe在zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org -------------- 下一部分 -------------- 一个HTML附件被移除... URL: <http://www.zeuux.org/pipermail/zeuux-universe/attachments/20131223/fa04541c/attachment.html>
2013年12月24日 星期二 15:26
所谓浮点数,小数点的位置可能是浮动的,如果浮动了小数点,误差就不会发生在小数点后第 11 位。而可能在更高的位或者更低位。 注意看我对这个数字不断乘 9 ,在 49180762728.93 这一行开始已经不精确了,最后两位数字被截断了。而当有效数字增加的时候,甚至可能出现整数位也不精确的情况。 (注:这里使用 lua 的原因在于 lua 的数字使用 double 类型计算) $ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > 92542.2817 92542.2817 > _*9 832880.5353 > _*9 7495924.8177 > _*9 67463323.3593 > _*9 607169910.2337 > _*9 5464529192.1033 > _*9 49180762728.93 > _*9 442626864560.37 > _*9 3983641781043.3 > _*9 35852776029390 > _*9 3.2267498426451e+14 > _*9 2.9040748583806e+15 > _*9 2.6136673725425e+16 > 如果使用除法呢?小数点又可能精确到 11 位以下: 下图中 0.00015718640451151 在小数点后具有 17 个有效数字。 > 9.2817 9.2817 > _/9 1.0313 > _/9 0.11458888888889 > _/9 0.012732098765432 > _/9 0.0014146776406036 > _/9 0.00015718640451151 > _/9 1.7465156056834e-05 > _/9 1.9405728952038e-06 2013/12/23 Kermit.Mei <kermit.mei在gmail.com> > 感谢pansz兄的指点,抱歉,我一直在想您给的这个规律怎么用,所以现在才回复。 > > 很遗憾最后我还是没能想到一个算法,用这个"0.5次幂规律"来检测我的double是否 > 有误差。最后,我想了一个十分简单的解决方案: > > 把结果double转换成字符串,检验字符串中小数点后的11位(因为我迄今见过的最大 > 的误差就在这位上),然后从第11位开始做一次四舍五入。把结果最后的 '0' 去掉,如 > 过最后的字符串长度比传入的长度小 5, 那么我就认为它做了校验误差的操作,比如: > > "92542.28170000001" > 对字符串 小数点后第11位"四舍五入" > "92542.2817" > 对比字符串长度,发现长度相差 5,就认为剔除误差了。 > > > 不过最后再顺便问一句:按照下面那个 0.5幂次的规律,我能否得出这个结论: > double保存的数如果存在误差,那么这个误差数小数最后一位只可能是:1, 5, 9 > 三者之一? 如果能得出这个结论,那么我就可以用这种字符串过滤方法算得更 > 精确一步。 > > > Thanks > B.R > Kermit > > 在 18 Dec 2013,16:05,pansz <pan.shizhu在gmail.com> 写道: > > double 是使用二进制存储的。 > > 所有的十进制有限位整数都可以无误差转换成二进制有限位整数。 > > 但十进制有限位小数无法转化为二进制有限位小数。如果一个十进制小数对应一个无限位二进制小数,则该小数使用 double > 保存会造成误差。通过这一点可以让你发现产生误差的规律。 > > 比较明确的说: > 925422817 这样的整数,使用 double 保存绝对不会有误差。 > 0.5,0.25,0.125,0.0625,0.03125,0.015625 等等这样的 0.5 的幂次,使用 double 保存不会有误差。 > 使用上述数据一次加成的,不会有误差。 > 例如 0.625 = 0.5+0.125 ,这个数使用 double 保存不会有误差 > 例如 99999.5625 = 99999 + 0.5 +0.0625 ,这个数使用 double 保存不会有误差 > > 无法通过上述方法分解的小数,使用 double 保存,都会发生误差。 > > 以上规律告诉你了什么数保存会发生误差。至于怎么使用看自己了。如果你只需要保存不需要计算的话,可以直接将这个数保存为 925422817 > 这种整数,注意整数就算保存在 double 类型里面也不会有误差。 > > > > 2013/12/11 Kermit.Mei <kermit.mei在gmail.com> > >> Hello all, >> >> 我遇到一个奇怪的问题,有些数字,比如我已经发现的这个: >> 92542.2817 >> >> 如果我把它作为浮点数存储到C++变量中,如: >> double number = 92542.2817; >> >> 则不管是使用stringstream把它转换为字符串,还是在调试器里面 >> 看这个变量赋值后的值,都是: >> >> 92542.28170000001 >> >> 这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。 >> >> 因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个 >> 问题了? >> >> >> 求指教? 多谢! >> >> B.R >> Kermit >> _______________________________________________ >> zeuux-universe mailing list >> zeuux-universe在zeuux.org >> http://www.zeuux.org/mailman/listinfo/zeuux-universe >> >> ZEUUX Project - Free Software, Free Society! >> http://www.zeuux.org > > > _______________________________________________ > zeuux-universe mailing list > zeuux-universe在zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org > > > _______________________________________________ > zeuux-universe mailing list > zeuux-universe在zeuux.org > http://www.zeuux.org/mailman/listinfo/zeuux-universe > > ZEUUX Project - Free Software, Free Society! > http://www.zeuux.org > -------------- 下一部分 -------------- 一个HTML附件被移除... URL: <http://www.zeuux.org/pipermail/zeuux-universe/attachments/20131224/67f90357/attachment.html>
Zeuux © 2024
京ICP备05028076号