我正在执行一些需要表示的数据类型转换 uint, long, ulongdecimal 作为 IEEE 754 双浮点值。我希望能够在执行转换之前检测 IEEE 754 数据类型是否不能包含该值。

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

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

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

编辑: Int32 能够完全表达为 IEE-754。还有 Decimal 数据类型是问题的重要组成部分。

重要更新: 如果您提到这个问题,您还应该阅读这个问题: IEEE-754 双精度(64 位浮点)与 IEEE-754 双精度(64 位浮点)对比重温长(64 位整数)

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

此外,CLR System.Double 类型中似乎存在错误,因为它无法正确允许这些值往返。

有帮助吗?

解决方案

简单的解决方案可能类似于(如果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的确切值)。

其他提示

这主要取决于您正在操作的号码范围。只要您的数字在 15 位以内(对于 双倍的),对于整数,您应该保持安全。

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

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

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

我假设(我确定在Java的情况下但不知道C#并且懒得检查)int是32位而long是64位。因此,为了确保int可以适合双倍而没有任何问题,无论是签名还是不签名。

对于ulong,你只需要高于第52位的所有位都是((aULong <!> amp; <!> amp; 0xFFF0000000000000)== 0)。

很长一段时间,你必须将其登录考虑在内。由于Long是第二补码,但IEEE754不是(只有负位),它认为将负长转换为正(* -1)并检查为正数是安全的。因此,如果长期为负数,则首先将其设为-1(对于正数不做任何事情)。然后,检查它像ulong。

希望这有帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top