浮动数字的问题 [英] The problem with floating numbers

查看:120
本文介绍了浮动数字的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

看一下这个C#的代码:

Hello,
Take a look at this C#'s code:

double f = 10.123 - 10.0;
Console.WriteLine(f);



结果必须是'0.123',但这里是'0.122999999999999'!!

有什么问题?

我知道差异是Epsilon,但是如果我想要真正的结果呢?



感谢提前!


The result must be '0.123', but here it is '0.122999999999999'!!
What's the problem??
I know that the difference is Epsilon, but what if I would like the real result?

Thank's in advance!

推荐答案

你不能得到真正的结果:每个计算机科学家应该知道关于浮点运算的知识 [ ^ ]。



作为解决方法,您可以使用输出表示中提供的舍入:

You cannot have the real result: "What Every Computer Scientist Should Know About Floating-Point Arithmetic"[^].

As workaround you might use the rounding provided on output representation:
double f = 10.123 - 10.0;
Console.WriteLine(f.ToString("0.###"));


这是浮点计算机算术的固有属性,即精度有限的算术。



例如,取数字 1/7 = 0.142857142857142857 142857 ...

如果现在计算精度有限的7x(1/7)(例如纸和笔)你会看到相同的效果:



7x(1/7) < TR> < TD> 0.14 < TD> 0.142857
precision 1/7 舍入到2位
0 0 0 0.00
1 0.1 0.7 0.70
2 0.98 0.98
3 0.142 0.994 0.99
4 0.1428 0.9996 1.00
5 0.14285 0.99995 1.00
6 0.999999 1.00
... ... ...
12 0.142857142857 0.999999999999 1.00
... ... ... ...




类似于计算机算术,你必须正好处理这个问题。

如果使用浮点数,你必须考虑三个问题:

This is a inherent property of floating-point computer arithmetic, i.e. arithmetic with limited precision.

As example, take the number 1/7 = 0.142857142857142857142857...
If you now calculate 7x(1/7) with limited precision (e.g. with paper and pencil) you see the same effect:

precision1/77x(1/7)rounding to 2 digits
0000.00
10.10.70.70
20.140.980.98
30.1420.9940.99
40.14280.99961.00
50.142850.999951.00
60.1428570.9999991.00
.........
120.1428571428570.9999999999991.00
............


Analogous with computer arithmetic, you have to take care of exactly this issue.
You have to consider three issues if working with floating point numbers:


  1. 决定显示数字的精度(例如以米[m]给出的物理长度,精确到1毫米[mm] - >显示精度= 3 - >在显示时舍入到3个小数位)。例如。 d.ToString(F3)
  2. 确定用于相等和关系操作的比较增量(例如= =,!=,<,< =,> =,>)。例如。显示精度+ 1 - >请参阅揭开C#浮点平等和关系操作的神秘面纱 [< a href =http://www.codeproject.com/Articles/383871/Demystify-Csharp-floating-point-equality-and-relattarget =_ blanktitle =New Window> ^ ] 。例如。 var epsilon = new RealExtension.Epsilon(1E- 4 ); ... if(x.EQ(y,epsilon))...
  3. 不要直接或间接使用 GetHashCode()浮点数,例如作为字典和散列集合的关键(由于浮点数的不精确性)。

  1. Decide on a precision for displaying numbers (e.g. a physical length given in meters [m] and precise to 1 millimeter [mm] --> display precision = 3 --> rounding to 3 fraction digits while displaying). E.g. d.ToString("F3").
  2. Decide on a comparison delta used for equality and relation operations (like ==, !=, <, <=, >=, >). E.g. display precision + 1 --> see Demystify C# floating-point equality and relation operations[^]. E.g. var epsilon = new RealExtension.Epsilon(1E-4);...if (x.EQ(y, epsilon)) ...
  3. Do not use GetHashCode() on floating point numbers, neither directly nor indirectly e.g. as key in dictionaries and hash collections (due to the not precise nature of the floating point numbers).





干杯

Andi



PS:不要在数字域之间进行反复播放。这是一个坏习惯,从长远来看,它会让你付出更多的代价。决定一个域名并留在其中。 单个具有与上述相同的问题,它只是转移到其他地方。



Cheers
Andi

PS: Do not cast forth and back between number domains. This is a bad habit that cost you more in the long run than it helps. Decide on a domain and stay in it. Single has the same problem as stated above, it is simply shifted to other places.


MSDN:

单个值的精度低于Double值。由于精度的差异,转换为看似等效的Double的单个值通常不等于Double值。在以下示例中,将相同除法运算的结果分配给Double和Single值。将Single值强制转换为Double后,两个值的比较显示它们不相等。

Single values have less precision than Double values. A Single value that is converted to a seemingly equivalent Double often does not equal the Double value because of differences in precision. In the following example, the result of identical division operations is assigned to a Double and a Single value. After the Single value is cast to a Double, a comparison of the two values shows that they are unequal.



http://msdn.microsoft.com/en-us/library/system。 double.aspx?cs-save-lang = 1& cs-lang = csharp#code-snippet-7 [ ^ ]



写行时


http://msdn.microsoft.com/en-us/library/system.double.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-7[^]

When you write the line

double f = 10.123 - 10.0;



与写入相同


it is the same as to write

double f = 10.123d - 10.0d;



为C#默认是双精度浮点...

没有办法得到确切的值,但你可以更接近(或进一步)它...你所要做的就是决定什么您需要的精度......

例如将您的行更改为


as C# default is to double precision floating point...
There is no way to get the exact value but you can get closer (or further) to it...All you have to do is to decide what the precision you need...
for example by changing your line to

double f = 10.123f - 10.0f



你会得到0.12300014495849609的结果......

正如你在底线所看到的,你将不得不在使用浮点数时进行向上/向下舍入...



但是你很幸运 - 这个浮点问题是微软知道的,还有一种可以用于浮点计算的类型 - 十进制 [ ^ ] ...

它有它的缺点(阅读MSDN页面),但对于您的范围(根据您的情况),它将给出正确的答案。试试......


you will get the result of 0.12300014495849609...
As you can see at the bottom line you will have to play with rounding up/down while using floating point numbers...

However you are fortunate - this problem of floating points was known to Microsoft and there is an other type that can be used for floating point computations - decimal[^]...
It has it drawbacks (read the MSDN page) but for your range (according to your case) it will give the correct answer. Try...

decimal f = 10.123m - 10.0m;


这篇关于浮动数字的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆