我最近遇到了非规范化的定义,我理解有些数字不能用标准化的形式表示,因为它们太小而不适合它的相应类型.根据IEEE
所以我试图做的是当一个非规范化数字作为参数传递时捕获,以避免使用这个数字进行计算.如果我理解正确,我只需要在非规范化范围内查找数字
private bool IsDenormalizedNumber(float number)
{
return Math.Pow(2, -149) <= number && number<= ((2-Math.Pow(2,-23))*Math.Pow(2, -127)) ||
Math.Pow(-2, -149) <= number && number<= -((2 - Math.Pow(2, -23)) * Math.Pow(2, -127));
}
Run Code Online (Sandbox Code Playgroud)
我的解释是否正确?
我认为更好的方法是检查这些位。标准化或非标准化是二进制表示的特征,而不是值本身的特征。因此,您将能够通过这种方式更可靠地检测它,并且无需进行潜在危险的浮点比较即可做到这一点。
我为您整理了一些可运行的代码,以便您可以看到它的工作原理。我根据有关双打的类似问题改编了此代码。检测非正规数比完全删除指数和有效数要简单得多,因此我能够大大简化代码。
至于它为什么起作用......指数以偏移表示法存储。指数的 8 位可以取值 1 到 254(0 和 255 保留用于特殊情况),然后将它们偏移调整 -127,产生 -126 (1-127) 到 127 (254-127) 的标准化范围)。在非正规情况下指数设置为 0。我认为这只是必需的,因为 .NET 不存储有效数上的前导位。根据 IEEE 754,它可以以任何一种方式存储。看来 C# 已选择放弃它,转而使用符号位,尽管我没有任何具体细节来支持这一观察结果。
无论如何,实际的代码非常简单。所需要的只是删除存储指数的 8 位并测试 0。0 周围有一个特殊情况,下面将对此进行处理。
注意:根据评论讨论,此代码依赖于特定于平台的实现细节(在此测试用例中为 x86_64)。正如 @ChiuneSugihara 指出的,CLI 不确保这种行为,并且在其他平台(例如 ARM)上可能有所不同。
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("-120, denormal? " + IsDenormal((float)Math.Pow(2, -120)));
Console.WriteLine("-126, denormal? " + IsDenormal((float)Math.Pow(2, -126)));
Console.WriteLine("-127, denormal? " + IsDenormal((float)Math.Pow(2, -127)));
Console.WriteLine("-149, denormal? " + IsDenormal((float)Math.Pow(2, -149)));
Console.ReadKey();
}
public static bool IsDenormal(float f)
{
// when 0, the exponent will also be 0 and will break
// the rest of this algorithm, so we should check for
// this first
if (f == 0f)
{
return false;
}
// Get the bits
byte[] buffer = BitConverter.GetBytes(f);
int bits = BitConverter.ToInt32(buffer, 0);
// extract the exponent, 8 bits in the upper registers,
// above the 23 bit significand
int exponent = (bits >> 23) & 0xff;
// check and see if anything is there!
return exponent == 0;
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
-120, denormal? False
-126, denormal? False
-127, denormal? True
-149, denormal? True
Run Code Online (Sandbox Code Playgroud)
来源:
从 c# 中的 double 中提取尾数和指数
https://en.wikipedia.org/wiki/IEEE_floating_point
https://en.wikipedia.org/wiki/Denormal_number
http://csharpindepth.com/Articles/General/FloatingPoint。 ASPX
代码改编自:
Extracting mantissa and exponent from double in c#
| 归档时间: |
|
| 查看次数: |
1069 次 |
| 最近记录: |