【问题标题】:Why do i get nan after swapping bits in long double value?为什么我在交换长双精度位后得到 nan?
【发布时间】:2020-09-23 03:54:12
【问题描述】:

我必须为我的班级编写一个程序,以二进制表示的一些 long double 值交换 2 组位。我知道在 IEEE-754 标准中,当整个指数都被填充时,就会出现 nan 。但在我的情况下,它并没有完全填满,所以我认为 nan 没有理由。我不知道为什么会这样。我多次调试我的代码,它似乎工作正常。我认为与 char 数组的对话并返回到十进制是正确的,因为当我从 main 中删除 ld_switch_chunks 函数时,程序会打印与开始时相同的数字。

#include <stdio.h>

typedef union b_long_double
{
    char bin[16];
    long double num;
}b_long_double;



// char array to long double conversation
void transform_to_ld(const char * in)
{
    b_long_double tmp;
    tmp.num=0;
    for(int i=0; i<16; ++i)
        tmp.bin[i] = 0;
    for(int i=0; i<16; ++i)
    {
        char total = 0;
        for(int j=0; j<8;++j)
        {
            char current = 0;
            if(in[(i*8)+j] == 1)
            {
                current += 1;
                current <<= j;
                total |= current;
            }
        }
        tmp.bin[i] = total;
    }
    printf("%Lf\n", tmp.num);
}


//splits long double value to array of chars 
void split_ld_to_bin(const char* in, char* out)
{
    for(int i=0; i<16; ++i)
    {
        char current = in[i];
        for(int j=0; j<8;++j)
        {
            int index = i*8+j;
            out[index] = current & 1;
            current >>= 1;
        }
    }

}


//swaps 2 chunks of bits
void ld_switch_chunks(char * in)
{
    int first_bit=77; //lead bit of first chunk
    int second_bit=63; //lead bit of second chunk
    int length=6; // length of chunk

    if(first_bit < 0 || first_bit > 79)
    {
        printf("Invalid input\n");
        return;
    }

    if(second_bit < 0 || second_bit > 79 || first_bit == second_bit)
    {
        printf("Invalid input\n");
        return;
    }

    if(length <= 0 || length > 40 || (second_bit-length) < 0 || (first_bit-length) < 0
       || ( second_bit>first_bit && (second_bit-length) <= first_bit) || (first_bit>second_bit && (first_bit-length) <= second_bit))
    {
        printf("Invalid input\n");
        return;
    }


    char tmp = 0;
    if(first_bit > second_bit)
        for(int i=0; i<length; ++i)
        {
            tmp = in[second_bit-i];
            in[second_bit-i] = in[first_bit-i];
            in[first_bit-i] = tmp;
        }
    else
        for(int i=0; i<length; ++i)
        {
            tmp = in[first_bit-i];
            in[first_bit-i] = in[second_bit-i];
            in[second_bit-i] = tmp;
        }
}


void print_ld(char* ld_array)
{
    for(int i=79; i>=0; --i)
        printf("%d", ld_array[i]);
    printf("\n");
}


int main()
{
    b_long_double input;
    input.num = 15.375; // input number
    char binary[128] = {};
    split_ld_to_bin(input.bin, binary);
    print_ld(binary);


    ld_switch_chunks(binary);
    print_ld(binary);


    transform_to_ld(binary);
}

输出是:

01000000000000101111011000000000000000000000000000000000000000000000000000000000
01111101000000100000001000000000000000000000000000000000000000000000000000000000
nan

,其中第一行是初始数据的二进制,第二行是交换集的二进制,第三行必须是新的 long double 值,由位交换产生。 我想知道发生这种情况的原因。

【问题讨论】:

  • 检查 IEEE 规范。可能还有其他模式是 NaN。
  • long double 在您的环境中是 80 位扩展精度还是 128 位四倍精度类型?
  • @Bob__,它是 128 位的值,但只使用了 80 位。其他数据用于对齐
  • 您应该edit 您的问题并解释在浮点数中交换位的目的是什么以及为什么您认为结果应该是有效的数字表示。你检查char bin[16] 和字符串表示之间的转换在两个方向上都是正确的吗?
  • @Bodo,我编辑了。这是我电脑课的作业。我认为输出应该是一个数字,因为在二进制中它看起来不像 ieee-754 中的 nan。我通过删除 main 中的 ld_switch_chunks 来检查对话。

标签: c ieee-754 long-double


【解决方案1】:

深入到这个关于x86 80-bit extended precision format 的维基百科页面(我认为这是 OP 正在搞乱的那个),我们可以找到一个关于“x86 扩展精度值的字段解释”的表格。

它说,关于位 63 为零(如在 OP 的示例中):

不正常。仅在 8087 和 80287 上生成。80387 及以后的版本将此视为无效操作数。
...
与单精度和双精度格式相比,这种格式不使用隐式/隐藏位。相反,位 63 包含有效数的整数部分,位 62-0 包含小数部分。所有标准化数字的第 63 位将为 1。

这应该可以解释 NaN。

【讨论】:

    猜你喜欢
    • 2012-11-07
    • 1970-01-01
    • 2014-05-08
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 2018-12-23
    • 2019-11-06
    相关资源
    最近更新 更多