规格化数C# [英] Denormalized numbers C#

查看:180
本文介绍了规格化数C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近碰到非规范化的定义,据我所知,有一些不能在标准化的形式,因为它们太小,以适应其相应类型来表示一些数字。符合IEEE

I recently came across denormalized definition and I understand that there are some numbers that cannot be represented in a normalized form because they are too small to fit into its corresponding type. According with IEEE

所以,我试图做的是抓时,非正规数被作为参数,以避免与这个数字计算过去了。如果我的理解是否正确我只是需要寻找数字规格化

So what I was trying to do is catch when a denormalized number is being passed as a parameter to avoid calculations with this numbers. If I am understanding correct I just need to look for numbers within the Range of denormalized

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));
}



是我的理解是否正确?

Is my interpretation correct?

推荐答案

我想一个更好的办法是检查位。归一化或非规范化是二进制表示的特性,而不是本身的价值。因此,您将能更可靠地检测这种方式,你可以不和潜在危险的浮点比较这么做。

I think a better approach would be to inspect the bits. Normalized or denormalized is a characteristic of the binary representation, not of the value itself. Therefore, you will be able to detect it more reliably this way and you can do so without and potentially dangerous floating point comparisons.

我把一些可运行的代码给你,这样您就可以看到它的工作。我从双打方面类似的问题适应了这个代码。检测非正规比完全切除指数和有效简单得多,所以我能够大大简化代码。

I put together some runnable code for you, so that you can see it work. I adapted this code from a similar question regarding doubles. Detecting the denormal is much simpler than fully excising the exponent and significand, so I was able to simplify the code greatly.

至于为什么它的工作原理...指数是存储在偏置符号。指数的8位可能需要1至254(0和255被保留用于特殊情况)的值,它们就会通过偏移-127调整屈服-126(1-127)的标准化范围127(254-127 )。该指数在非正规的情况下设置为0。我想,这是因为.NET并不存储在尾数领先位时才需要。根据IEEE 754,它可以存储方式。看来,C#已经选择了,取而代之的是符号位掉到地上,虽然我没有任何具体细节来支持这一意见。

As for why it works... The exponent is stored in offset notation. The 8 bits of the exponent can take the values 1 to 254 (0 and 255 are reserved for special cases), they are then offset adjusted by -127 yielding the normalized range of -126 (1-127) to 127 (254-127). The exponent is set to 0 in the denormal case. I think this is only required because .NET does not store the leading bit on the significand. According to IEEE 754, it can be stored either way. It appears that C# has opted for dropping it in favor of a sign bit, though I don't have any concrete details to back that observation.

在任何情况下,实际的代码非常简单。所需要的只是切除了8位存储的指数和试验0周围有0的特殊情况,这将在下面处理。

In any case, the actual code is quite simple. All that is required is to excise the 8 bits storing the exponent and test for 0. There is a special case around 0, which is handled below.

注意每评论的讨论,这个代码依赖于平台的具体实施细则(x86_64的在本次测试的情况下)。由于@ChiuneSugihara指出的那样,CLI不能确保这种行为,它可能会在其他平台上,如ARM不同。

NOTE: Per the comment discussion, this code relies on platform specific implementation details (x86_64 in this test case). As @ChiuneSugihara pointed out, the CLI does not ensure this behavior and it may differ on other platforms, such as 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;
        }
    }
}



输出是:

The output is:

-120, denormal? False
-126, denormal? False
-127, denormal? True
-149, denormal? True

来源:结果
从双在c#结果
https://en.wikipedia.org/wiki/IEEE_floating_point 结果
https://en.wikipedia.org/wiki/Denormal_number 结果
http://csharpindepth.com/Articles/General/FloatingPoint.aspx

Sources:
extracting mantissa and exponent from double in c#
https://en.wikipedia.org/wiki/IEEE_floating_point
https://en.wikipedia.org/wiki/Denormal_number
http://csharpindepth.com/Articles/General/FloatingPoint.aspx

代码改编自:结果
从双在c#提取尾数和指数

Code adapted from:
extracting mantissa and exponent from double in c#

这篇关于规格化数C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆