我正在执行一些数据类型转换,我需要将uint,long,ulong和decimal表示为IEEE 754双浮点值.我希望能够在执行转换之前检测IEEE 754数据类型是否包含该值.
一个强力解决方案是将一个try-catch包装在一个强制转换器周围,以便查找OverflowException.阅读CLR documentation中的某些内容意味着某些转换只是默默地改变了值而没有任何例外.
有没有任何万无一失的方法来做这个检查?我正在寻求完整性而非易于实施.我有一种感觉,我将仔细阅读IEEE 754规范并仔细检查matissa和exponent ……
我应该补充一点,我最关心的是准确地表示整数,浮点精度的损失是次要问题(但仍值得考虑).
编辑:Int32能够完全表达为IEE-754.此外,Decimal数据类型也是问题的一部分.
重要更新:如果您提到这个问题,您还应该阅读这个问题:IEEE-754 Double (64-bit floating point) vs. Long (64-bit Integer) Revisited
它注意到答案中的一个缺陷,其中一些非常大的值也能够由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的确切值).