从无符号长整型到浮点型,从圆到最接近 [英] Converting from unsigned long long to float with round to nearest even

查看:212
本文介绍了从无符号长整型到浮点型,从圆到最接近的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要写一个从unsigned long long到float的函数,并且舍入应该是最接近的。
我不能只是做一个C ++类型转换,因为AFAIK的标准没有指定舍入。
我正在考虑使用boost :: numeric,但我没有找到任何有用的铅阅读文档后。这可以使用该库吗?
当然,如果有一个替代,我会很高兴使用它。

I need to write a function that rounds from unsigned long long to float, and the rounding should be toward nearest even. I cannot just do a C++ type-cast, since AFAIK the standard does not specify the rounding. I was thinking of using boost::numeric, but i could not find any useful lead after reading the documentation. Can this be done using that library? Of course, if there is an alternative, i would be glad to use it.

任何帮助将非常感激。

编辑:添加一个例子,使事情更清晰。
假设我想将0xffffff7fffffffff转换为其浮点表示形式。 C ++标准允许以下任意一种:

Adding an example to make things a bit clearer. Suppose i want to convert 0xffffff7fffffffff to its floating point representation. The C++ standard permits either one of:


  1. 0x5f7fffff〜1.9999999 * 2 ^ 63

  2. 0x5f800000 = 2 ^ 64

现在,如果您将round的限制添加到最接近的偶数,则只有第一个结果可以接受。

Now if you add the restriction of round to nearest even, only the first result is acceptable.

推荐答案

由于在源中有这么多位,不能在 float 你不能(显然)依赖于语言的转换,你必须自己做。

Since you have so many bits in the source that can't be represented in the float and you can't (apparently) rely on the language's conversion, you'll have to do it yourself.

我设计了一个计划,可能或可能不会帮助你。基本上,在 float 中有31位表示正数,因此我选择源号中的31个最高有效位。然后我保存和屏蔽掉所有低位。然后根据低位的值,我向上或向下舍入新LSB,最后使用 static_cast 创建一个 float

I devised a scheme that may or may not help you. Basically, there are 31 bits to represent positive numbers in a float so I pick up the 31 most significant bits in the source number. Then I save off and mask away all the lower bits. Then based on the value of the lower bits I round the "new" LSB up or down and finally use static_cast to create a float.

我留在一些couts,你可以根据需要删除。

I left in some couts that you can remove as desired.

const unsigned long long mask_bit_count = 31;

float ull_to_float2(unsigned long long val)
{
    // How many bits are needed?
    int b = sizeof(unsigned long long) * CHAR_BIT - 1;
    for(; b >= 0; --b)
    {
        if(val & (1ull << b))
        {
            break;
        }
    }

    std::cout << "Need " << (b + 1) << " bits." << std::endl;

    // If there are few enough significant bits, use normal cast and done.
    if(b < mask_bit_count)
    {
        return static_cast<float>(val & ~1ull);
    }

    // Save off the low-order useless bits:
    unsigned long long low_bits = val & ((1ull << (b - mask_bit_count)) - 1);
    std::cout << "Saved low bits=" << low_bits << std::endl;

    std::cout << val << "->mask->";
    // Now mask away those useless low bits:
    val &= ~((1ull << (b - mask_bit_count)) - 1);
    std::cout << val << std::endl;

    // Finally, decide how to round the new LSB:
    if(low_bits > ((1ull << (b - mask_bit_count)) / 2ull))
    {
        std::cout << "Rounding up " << val;
        // Round up.
        val |= (1ull << (b - mask_bit_count));
        std::cout << " to " << val << std::endl;
    }
    else
    {
        // Round down.
        val &= ~(1ull << (b - mask_bit_count));
    }

    return static_cast<float>(val);
}

这篇关于从无符号长整型到浮点型,从圆到最接近的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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