在 C# 中比较双精度值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1398753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing double values in C#
提问by stack_pointer is EXTINCT
I've a double
variable called x
.
In the code, x
gets assigned a value of 0.1
and I check it in an 'if' statement comparing x
and 0.1
我有一个double
名为x
. 在代码中,x
被分配了一个值,0.1
我在一个“if”语句中检查它比较x
和0.1
if (x==0.1)
{
----
}
Unfortunately it does not enter the if
statement
不幸的是它没有进入if
语句
Should I use
Double
ordouble
?What's the reason behind this? Can you suggest a solution for this?
我应该使用
Double
还是double
?这背后的原因是什么?你能为此提出一个解决方案吗?
采纳答案by Vilx-
It's a standard problem due to how the computer stores floating point values. Search here for "floating point problem" and you'll find tons of information.
由于计算机如何存储浮点值,这是一个标准问题。在此处搜索“浮点问题”,您会发现大量信息。
In short – a float/double can't store 0.1
precisely. It will always be a little off.
简而言之 - 浮点数/双0.1
精度不能精确存储。它总是会有点偏离。
You can try using the decimal
type which stores numbers in decimal notation. Thus 0.1
will be representable precisely.
您可以尝试使用decimal
以十进制表示法存储数字的类型。因此0.1
将是可精确表示的。
You wanted to know the reason:
你想知道原因:
Float/double are stored as binary fractions, not decimal fractions. To illustrate:
浮点数/双精度数存储为二进制分数,而不是十进制分数。为了显示:
12.34
in decimal notation (what we use) means
12.34
十进制表示法(我们使用的)表示
1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2
The computer stores floating point numbers in the same way, except it uses base 2
: 10.01
means
计算机以相同的方式存储浮点数,除了它使用 base 2
:10.01
表示
1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2
Now, you probably know that there are some numbers that cannot be represented fully with our decimal notation. For example, 1/3
in decimal notation is 0.3333333…
. The same thing happens in binary notation, except that the numbers that cannot be represented precisely are different. Among them is the number 1/10
. In binary notation that is 0.000110011001100…
.
现在,您可能知道有些数字无法用我们的十进制表示法完全表示。例如,1/3
十进制表示法是0.3333333…
。同样的事情发生在二进制表示法中,只是不能精确表示的数字是不同的。其中有数1/10
。用二进制表示法是0.000110011001100…
。
Since the binary notation cannot store it precisely, it is stored in a rounded-off way. Hence your problem.
由于二进制符号不能精确存储它,所以它以四舍五入的方式存储。因此你的问题。
回答by sharptooth
Comparing floating point number can't always be done precisely because of rounding. To compare
由于四舍五入,不能总是精确地比较浮点数。比较
(x == .1)
the computer really compares
电脑真的比较
(x - .1) vs 0
Result of sybtraction can not always be represeted precisely because of how floating point number are represented on the machine. Therefore you get some nonzero value and the condition evaluates to false
.
由于浮点数在机器上的表示方式,sybtraction 的结果不能总是精确地表示。因此,您会得到一些非零值,并且条件评估为false
。
To overcome this compare
为了克服这种比较
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
回答by Massif
Floating point number representations are notoriously inaccurate because of the way floats are stored internally. E.g. x
may actually be 0.0999999999
or 0.100000001
and your condition will fail. If you want to determine if floats are equal you need to specify whether they're equal to within a certain tolerance.
由于浮点数在内部存储的方式,浮点数表示是出了名的不准确。例如,x
实际上可能是0.0999999999
或0.100000001
并且您的条件将失败。如果要确定浮点数是否相等,则需要指定它们是否在某个容差范围内相等。
I.e.:
IE:
if(Math.Abs(x - 0.1) < tol) {
// Do something
}
回答by Hans Ke?ing
Double and double are identical.
double 和 double 是相同的。
For the reason, see http://www.yoda.arachsys.com/csharp/floatingpoint.html. In short: a double is not an exact type and a minute difference between "x" and "0.1" will throw it off.
原因请参见http://www.yoda.arachsys.com/csharp/floatingpoint.html。简而言之:double 不是一种精确的类型,“x”和“0.1”之间的微小差异会使其消失。
回答by Hans Ke?ing
Exact comparison of floating point values is know to not always work due to the rounding and internal representation issue.
众所周知,由于舍入和内部表示问题,浮点值的精确比较并不总是有效。
Try imprecise comparison:
尝试不精确的比较:
if (x >= 0.099 && x <= 0.101)
{
}
The other alternative is to use the decimal data type.
另一种选择是使用十进制数据类型。
回答by Rune Grimstad
double
and Double
are the same (double
is an alias for Double
) and can be used interchangeably.
double
和Double
是相同的(double
是 的别名Double
)并且可以互换使用。
The problem with comparing a double with another value is that doubles are approximate values, not exact values. So when you set x
to 0.1
it may in reality be stored as 0.100000001
or something like that.
将双精度值与另一个值进行比较的问题在于双精度值是近似值,而不是精确值。因此,当您设置x
为0.1
它时,实际上可能会存储为0.100000001
或类似的内容。
Instead of checking for equality, you should check that the difference is less than a defined minimum difference (tolerance). Something like:
您应该检查差异是否小于定义的最小差异(容差),而不是检查是否相等。就像是:
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
回答by Lars Corneliussen
1) Should i use Double or double???
1)我应该使用双倍还是双倍???
Double
and double
is the same thing. double
is just a C# keyword working as alias for the class System.Double
The most common thing is to use the aliases! The same for string
(System.String
), int
(System.Int32
)
Double
并且double
是一回事。double
只是一个用作类别名System.Double
的C# 关键字最常见的是使用别名!string
( System.String
), int
( System.Int32
)同理
Also see Built-In Types Table (C# Reference)
另请参阅内置类型表(C# 参考)
回答by Timothy Walters
Double (called float in some languages) is fraut with problems due to rounding issues, it's good only if you need approximate values.
Double(在某些语言中称为 float)由于舍入问题而存在问题,只有在您需要近似值时才好。
The Decimal data type does what you want.
Decimal 数据类型可以满足您的需求。
For reference decimal and Decimal are the same in .NET C#, as are the double and Double types, they both refer to the same type (decimal and double are very different though, as you've seen).
对于参考,decimal 和 Decimal 在 .NET C# 中是相同的,double 和 Double 类型也是如此,它们都指代相同的类型(但正如您所见,decimal 和 double 非常不同)。
Beware that the Decimal data type has some costs associated with it, so use it with caution if you're looking at loops etc.
请注意 Decimal 数据类型有一些与之相关的成本,因此如果您正在查看循环等,请谨慎使用它。
回答by Alfred Myers
From the documentation:
从文档:
Precision in Comparisons The Equals method should be used with caution, because two apparently equivalent values can be unequal due to the differing precision of the two values. The following example reports that the Double value .3333 and the Double returned by dividing 1 by 3 are unequal.
比较精度 应谨慎使用 Equals 方法,因为两个明显等效的值可能因两个值的精度不同而不同。下面的示例报告 Double 值 .3333 和由 1 除以 3 返回的 Double 不相等。
...
...
Rather than comparing for equality, one recommended technique involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be due to differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, the two Double values that the previous code example found to be unequal.
一种推荐的技术不是比较相等性,而是定义两个值之间可接受的差异幅度(例如其中一个值的 0.01%)。如果两个值之间的差值的绝对值小于或等于该裕度,则该差值很可能是由于精度差异造成的,因此,这些值很可能相等。下面的示例使用此技术来比较 0.33333 和 1/3,这两个 Double 值在前面的代码示例中发现不相等。
So if you really need a double, you should use the techique described on the documentation. If you can, change it to a decimal. It' will be slower, but you won't have this type of problem.
所以如果你真的需要一个双人,你应该使用文档中描述的技术。如果可以,请将其更改为小数。它会更慢,但你不会遇到这种类型的问题。