当前位置: 首页 > 知识库问答 >
问题:

将decimal转换为double时的奇怪行为

宦烈
2023-03-14

我遇到了奇怪的问题时,铸造小数到双倍。

以下代码返回true:

Math.Round(0.010000000312312m, 2) == 0.01m //true

但是,当我将其强制转换为双倍时,它返回false:

(double)Math.Round(0.010000000312312m, 2) == (double)0.01m //false

这是记录在案的行为吗?当我被迫将decimal转换为Double时,我如何避免它?

Visual Studio的截图:

将Math.round铸造为双倍me,结果如下:

(double)Math.Round(0.010000000312312m, 2)   0.0099999997764825821   double
(double)0.01m   0.01    double
    null

不幸的是,我不能在较小的项目中重现这个问题。我想埃里克的回答解释了原因。

共有1个答案

萧渝
2023-03-14

人们在这里的评论中报告说,有时比较的结果是真的,有时是假的。

不幸的是,这是意料之中的。C#编译器、抖动和CPU都被允许在超过64位双精度的双精度上执行算术,因为它们认为合适。这意味着,有时看起来像“相同”的计算的结果在一次计算中可以以64位精度完成,在另一次计算中可以以80或128位精度完成,这两个结果在最后一位可能不同。

让我确保你明白我所说的“他们认为合适的”是什么意思。无论出于什么原因,你都可以得到不同的结果。在debug和Retail中可以得到不同的结果。如果让编译器在常量中进行计算,而让运行时在运行时进行计算,则可以得到不同的结果。调试器运行时可以得到不同的结果。您可以在运行库和调试器的表达式计算器中获得不同的结果。任何理由。双重算术天生就不可靠。这要归功于浮点芯片的设计;在这些芯片上的双重算术不可能在不造成相当大的性能损失的情况下变得更可重复。

顺便说一句,我已经在StackOverflow上多次回答了关于这个问题的各种变体。例如:

为什么在C#中用括号分隔和用语句分隔时浮点精度不同?

另外,如果您需要“拆开”一个double来查看它的位,我不久前编写的这段方便的代码非常有用。它要求您安装Solver Foundation,但这是免费下载的。

http://ericlippert.com/2011/02/17/looking-inside-a-double/

 类似资料:
  • 问题内容: 令人难以置信。为什么输出-124? 问题答案: 在Java中,an 是32位。A 是8 。 最原始的类型Java中的签名,,,,和long被编码在二进制补码。(类型为unsigned,并且sign的概念不适用于。) 在此数字方案中,最高有效位指定数字的符号。如果需要更多位,则将最高有效位(“ MSB”)简单复制到新的MSB中。 因此,如果你具有 并将其表示为 32位,则只需将1复制到左

  • 问题内容: 我正在实现一个接口,该接口的功能类似于可以包含某种对象的表的功能。该接口指定以下功能: 在我的实现中,我感到很困惑的是,我将表数据存储在2D 数组()中。当我需要返回值时,我想执行以下操作(假定只在包含double的列上调用,因此将没有): 但是- Java不允许强制转换为。将其强制转换为可以,因为它是一个对象,而不是基元,但是我的接口指定数据将以形式返回。 所以我有两个问题: 有什么

  • 矩形填充的图像改变其比例(宽度和高度改变)。 这显示了转换前后的svg。 有没有人有办法解决这个问题?

  • 我构建了一个小函数来将TimeStamp转换成LocalDate,并偶然发现了奇怪的行为。下面是代码: 我当地的时区是欧洲/柏林。现在,当调用时间戳0时,我得到正确的结果: 一切如期而至。但当我把它命名为第一年的日期时,它辜负了我的期望: 问题: 转换为Instant后缺少一天,所以UTC和欧洲/柏林的时区似乎在当时相隔一天加一小时

  • 问题内容: 这个问题已经在这里有了答案 : 为什么对泛型的这种使用不会引发运行时或编译时异常? (3个答案) 2年前关闭。 我正在使用Java 8。 我最近遇到了这个问题: 这不会引发java.lang.ClassCastException。这是为什么? 我一直在想和打电话。但是,当我尝试这样做时,它会按预期抛出异常。 问题答案: 它不会抛出,因为所有通用类型信息都已从编译后的代码中剥离(此过程称

  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方