【问题标题】:Error on converting from unsigned int to float从 unsigned int 转换为 float 时出错
【发布时间】:2016-04-10 20:36:43
【问题描述】:

背景:我在记录中有一些元素,其中一些元素可以是 float、unsigned int 或 unsigned long long。所以,我想使用 float 作为一个通用值来从读取这些元素的函数返回。

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

#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

【问题讨论】:

  • 32 位 float 没有足够的精度来存储 32 位无符号整数(或更糟的是 long long)的 exact 值,因为有效位精度是只有 24 位。尝试使用双精度,但不要使用 long long ints。
  • 注意:“返回无符号整数”行会导致未定义的行为,因为值超出范围

标签: c++ floating-point type-conversion


【解决方案1】:

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 在存储为浮点数时都表示相同的位。

【讨论】:

  • @M.M 感谢您的注意,我更正了这一点,是的,即使在 4294967200 和 4294967295 之间的数字也无法表示
  • 好的。我要说明的一点是 4294967295 没有这样表示(实际上它根本无法表示);如果您尝试代表该数字,则您展示的表示是一种可能性。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-07
    • 2014-04-05
    • 2012-04-28
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    相关资源
    最近更新 更多