3

我正在执行一些需要将 、 和 表示uintlongIEEE ulong754decimal双浮点值的数据类型转换。我希望能够在执行转换之前检测 IEEE 754 数据类型是否不能包含该值。

一个蛮力解决方案是在演员表周围包裹一个 try-catch 以双重查找OverflowException. 通读某些CLR 文档意味着某些转换只是默默地更改值,没有任何例外。

有没有万无一失的方法来做这个检查?我正在寻找完整性而不是易于实施。我有一种感觉,我将仔细阅读 IEEE 754 规范并仔细检查 matissa 和指数......

我应该补充一点,我关心的是准确地表示整数,而浮点精度的损失是次要的问题(但仍然值得考虑)。

编辑: Int32 能够完全表示为 IEE-754。数据类型也是Decimal问题的很大一部分。

重要更新:如果您指的是这个问题,您还应该阅读这个问题:IEEE-754 Double (64-bit floating point) vs. Long (64-bit Integer) Revisited

它指出了答案中的一个缺陷,即一些非常大的值也能够由 IEEE-754 精确表示。虽然这可能意味着该值将正确地往返,但出于我最初的目的(它将往返于 JavaScript)它不会。

CLRs System.Double 类型中似乎也存在一个错误,因为它不能正确地允许这些值往返。

4

3 回答 3

9

简单的解决方案可能类似于(如果 x 是 int):

if ((int)(double)x != x) { 
  // won't convert
} else {
  // will convert
}

等等,等等。

(double)x 将 x 从 int 转换为 double。(int) 然后将其再次转换回来。因此 (int)(double)x 将 int 转换为 double 然后返回。本质上,代码检查到 double 的转换是可逆的(因此 double 可以存储 int 的确切值)。

于 2009-10-21T15:31:39.917 回答
1

这主要取决于您使用的数字范围。只要您在 15 位以内(对于double),您应该对整数保持安全。

基本上,您需要考虑的是有效位数。因此,只要您的编号小于有效位数限制,它将保持准确;如果它变大,您将失去精度(即使这些是整数)。

因此,只要您的号码 < 2^53,您通常就很好。

于 2009-10-21T15:32:36.387 回答
1

IEEE 754 Double 有 52 位尾数,您正在从/转换为整数/长整数,因此很容易测试。如果您的整数消耗少于 52 位,那么它应该可以毫无问题地转换为 IEEE 754 double。

我假设(我肯定知道在 Java 的情况下,但不是 C# 并且懒得检查)int 是 32 位,long 是 64 位。因此,可以肯定 int 可以放入 double 中,而 sign 和 unsign 都没有任何问题。

对于 ulong,如果所有高于第 52 位的位都是一个,则只需 ((aULong && 0xFFF0000000000000) == 0)。

长期以来,您必须将其标志纳入考虑范围。由于 Long 是 2nd-complement 而 IEEE754 不是(只有负位),它认为将负 long 转换为正 (*-1) 并检查为正是安全的。因此,如果 long 是负数,请先用 -1 计时(对正数不做任何事情)。然后,像 ulong 一样检查它。

希望这可以帮助。

于 2009-10-21T15:52:01.917 回答