非规范化数字C#

Nan*_*dhi 11 c#

我最近遇到了非规范化的定义,我理解有些数字不能用标准化的形式表示,因为它们太小而不适合它的相应类型.根据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)

我的解释是否正确?

Kev*_*ett 6

我认为更好的方法是检查这些位。标准化或非标准化是二进制表示的特征,而不是值本身的特征。因此,您将能够通过这种方式更可靠地检测它,并且无需进行潜在危险的浮点比较即可做到这一点。

我为您整理了一些可运行的代码,以便您可以看到它的工作原理。我根据有关双打的类似问题改编了此代码。检测非正规数比完全删除指数和有效数要简单得多,因此我能够大大简化代码。

至于它为什么起作用......指数以偏移表示法存储。指数的 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#