我有一个double名为的变量x.在代码中,x获取一个值,0.1我在'if'语句中检查它,比较x和0.1
if (x==0.1)
{
----
}
Run Code Online (Sandbox Code Playgroud)
不幸的是它没有进入if声明
我应该使用Double或double?
这背后的原因是什么?你能为此建议一个解决方案吗?
Vil*_*lx- 92
由于计算机存储浮点值的方式,这是一个标准问题.在这里搜索"浮点问题",你会发现大量的信息.
简而言之 - 浮动/双重不能0.1精确存储.它总会有点偏差.
您可以尝试使用decimal以十进制表示法存储数字的类型.这样0.1就可以准确表达.
你想知道原因:
浮点/双精度存储为二进制分数,而非十进制分数.为了显示:
12.34 十进制表示法(我们使用的)表示
1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2
计算机以相同的方式存储浮点数,除了它使用base 2:10.01means
1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2
现在,您可能知道有些数字无法用十进制表示法完全表示.例如,1/3十进制表示法是0.3333333….同样的事情以二进制表示法发生,除了不能精确表示的数字是不同的.其中有数字1/10.用二进制表示法0.000110011001100….
由于二进制表示法不能精确地存储它,因此它以四舍五入的方式存储.因此你的问题.
Run*_*tad 41
double并且Double是相同的(double是别名Double),可以互换使用.
将double与另一个值进行比较的问题是,double是近似值,而不是精确值.因此,当你设置它时x,0.1它实际上可能存储为0.100000001或类似的东西.
您应该检查差异是否小于定义的最小差异(容差),而不是检查是否相等.就像是:
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
Run Code Online (Sandbox Code Playgroud)
Val*_*zub 19
你需要一个Math.Abson X-Y和a 的组合value来比较.
您可以使用以下Extension方法
public static class DoubleExtensions
{
const double _3 = 0.001;
const double _4 = 0.0001;
const double _5 = 0.00001;
const double _6 = 0.000001;
const double _7 = 0.0000001;
public static bool Equals3DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _3;
}
public static bool Equals4DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _4;
}
...
Run Code Online (Sandbox Code Playgroud)
因为你很少在double上调用方法,除非ToString我相信它非常安全的扩展.
然后你可以比较x和y喜欢
if(x.Equals4DigitPrecision(y))
sha*_*oth 10
由于四舍五入,因此不能总是精确地比较浮点数.比较
(x == .1)
Run Code Online (Sandbox Code Playgroud)
电脑真的比较
(x - .1) vs 0
Run Code Online (Sandbox Code Playgroud)
由于机器上如何表示浮点数,因此无法始终精确地表示缩减结果.因此,您获得一些非零值并且条件评估为false.
为了克服这种比较
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
Run Code Online (Sandbox Code Playgroud)
从文档:
比较精度应谨慎使用Equals方法,因为两个明显等效的值可能不相等,因为这两个值的精度不同.以下示例报告Double值.3333和通过除以1而返回的Double是不相等的.
...
一种推荐的技术不是比较相等性,而是涉及在两个值之间定义可接受的差异裕度(例如其中一个值的0.01%).如果两个值之间的差的绝对值小于或等于该边界,则差异可能是由于精度的差异,因此,值可能相等.以下示例使用此技术比较.33333和1/3,前两个代码示例发现的两个Double值不相等.
因此,如果您确实需要双倍,则应使用文档中描述的技术.如果可以,请将其更改为小数.它会慢一点,但你不会遇到这类问题.
| 归档时间: |
|
| 查看次数: |
90847 次 |
| 最近记录: |