如何测试数字转换是否会改变值?

我正在执行一些数据类型转换,我需要将uintlongulongdecimal为IEEE 754双浮点值。 我希望能够在执行转换之前检测IEEE 754数据类型是否包含该值。

一个powershell解决方案是将一个try-catch包装在一个强制转换器周围,以便查找OverflowException 。 阅读某些CLR文档意味着某些转换只是默默地更改值而没有任何exception。

有没有任何万无一失的方法来做这个检查? 我正在寻求完整性而非易于实施。 我有一种感觉,我将仔细阅读IEEE 754规范并仔细检查matissa和exponent ……

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

编辑: Int32能够完全表达为IEE-754。 此外, Decimal数据类型也是问题的一部分。

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

它注意到答案中的一个缺陷,其中一些非常大的值也能够由IEEE-754精确表示。 虽然这可能意味着该值将正确地往返,为了我的原始目的(它将往返JavaScript)它不会。

此外,CLRs 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 && 0xFFF0000000000000)== 0)。

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

希望这可以帮助。