我遇到了奇怪的问题时,铸造小数到双倍。
以下代码返回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
不幸的是,我不能在较小的项目中重现这个问题。我想埃里克的回答解释了原因。
人们在这里的评论中报告说,有时比较的结果是真的,有时是假的。
不幸的是,这是意料之中的。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。这是为什么? 我一直在想和打电话。但是,当我尝试这样做时,它会按预期抛出异常。 问题答案: 它不会抛出,因为所有通用类型信息都已从编译后的代码中剥离(此过程称
问题内容: 当我尝试将double数组转换为Double arrayList时,出现以下错误: 线程“主”中的异常java.lang.ClassCastException:[无法将D强制转换为java.lang.Double 下面是我的代码。 我正在将此列表与另一个列表进行比较,并将结果分配给另一个double变量。 请让我知道此错误的原因。 问题答案: las,不适用于原语。Apache com