从无符号 int 转换为浮点数时出错

Error on converting from unsigned int to float

本文关键字:浮点数 出错 转换 无符号 int      更新时间:2023-10-16

>背景:我在记录中有一些元素,其中某些元素可以是浮动的,无符号的int或无符号的长长。因此,我使用float作为从读取这些元素的函数返回的通用值。

但是,我在从无符号 int 转换为浮点数时看到了这个奇怪的错误。在打印值时,它会发生变化。我怎样才能避免它?我不应该从这个函数返回浮点数吗?

#include <iostream>
#include <limits>
using namespace std;
int main()
{
  unsigned int  myU = numeric_limits<unsigned int>::max();
  cout<<" myU is "<<myU<<'n'; //correct
  float myF = (float) myU;
  cout<<" back To Long "<<(unsigned long long ) myF<<'n'; //error?
  cout<<" back To unsigned int "<<(unsigned int ) myF<<'n'; //error?
  cout<<" to Float Without Fixed "<<(float) myU<<'n';//not clear, so have to use fixed
  cout<<" to Float With Fixed "<<fixed<<(float) myU<<'n';//error?
  cout<<" difference "<<myF-myU<<'n'; //error?
  cout<<" myU+32 "<<myU+32<<'n'; //-1+32=31 ==> understandable
}

使用 gcc 4.6.3 输出:

 myU is 4294967295
 back To Long 4294967296
 back To unsigned int 0
 to Float Without Fixed 4.29497e+09
 to Float With Fixed 4294967296.000000
 difference 1.000000
 myU+32 31

float (32-bit IEEE 754)4294967295的数字表示如下:

0       10011111      00000000000000000000000
sign    exponent      mantissa
(+1)    (2^32)        (1.0)

将其转换回整数(在本例中为长整型(的规则是:

sign * (2^exponent) * mantissa

结果将是4294967296它的尺寸适合为您填充long long,但太大而无法容纳unsigned int因此您将获得0以进行unsigned int转换。

请注意,问题在于用浮点数表示大数的限制,例如4294967295 4294967200当它们存储为浮点数时,两者都表示相同的位。

您看到的主要问题是浮点类型仅提供其分数部分的有限精度,这当然是很自然的,因为它只能容纳这么多信息。

现在,当您从unsigned int转换为float时,您使用的数字太长,无法放入分数部分。现在丢失了一些精度,并且您转换回整数格式,它可能会有所不同。对unsigned long long来说,结果只是一个更大的,但是在转换为unsigned int时,你会看到一个溢出