哲思官方群认证群组  - 讨论区

标题:[zeuux-universe] 浮点数 92542.2817在C++中无法使用?

2013年12月11日 星期三 18:40

Kermit.Mei kermit.mei在gmail.com
星期三 十二月 11 18:40:38 CST 2013

Hello all,

        我遇到一个奇怪的问题,有些数字,比如我已经发现的这个:
92542.2817

如果我把它作为浮点数存储到C++变量中,如:
double number = 92542.2817;

则不管是使用stringstream把它转换为字符串,还是在调试器里面
看这个变量赋值后的值,都是:

92542.28170000001

这个是多了 1e-9个单位,还有一些奇怪的数字会少这么个单位。

因为我的浮点保留位是用户自定义的,所以我现在不知道怎么应对这个
问题了?


求指教? 多谢!

B.R
Kermit

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

2013年12月12日 星期四 02:13

Alex Zhang cheungtifan在gmail.com
星期四 十二月 12 02:13:46 CST 2013

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>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

2013年12月12日 星期四 10:23

Kermit.Mei kermit.mei在gmail.com
星期四 十二月 12 10:23:53 CST 2013

感谢各位的回复!

用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>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

2013年12月18日 星期三 16:05

pansz pan.shizhu在gmail.com
星期三 十二月 18 16:05:15 CST 2013

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>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

2013年12月23日 星期一 12:08

Kermit.Mei kermit.mei在gmail.com
星期一 十二月 23 12:08:54 CST 2013

感谢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>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

2013年12月24日 星期二 15:26

pansz pan.shizhu在gmail.com
星期二 十二月 24 15:26:14 CST 2013

所谓浮点数,小数点的位置可能是浮动的,如果浮动了小数点,误差就不会发生在小数点后第 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>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-universe]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2024

    京ICP备05028076号