整数和浮点转换

时间:2017-03-14 13:16:35

标签: c++ type-conversion ieee-754

我在C ++中有一些关于(隐式)类型转换的小问题。

1。 float to int

float f = 554344.76;
int x1 = f;
std::cout << x1 << std::endl;

打印554344(向下舍入或缩小小数位),但在用float f = 5543444.76;替换它时,会打印5543445(向上舍入)。为什么它在第一种情况下四舍五入,在第二种情况下四舍五入?除此之外,对于更大的数字,它会产生完全奇怪的结果(例如5543444675.76变为5543444480)。为什么呢?

int x1 = f;long int x2 = f;之间的区别是什么?

2。 Long int to float

long int li;
float x3 = li;
std::cout << x3 << std::endl;

练习的解决方案表示值向下舍入并导致大数值的值不正确。如果我尝试long int li = 5435;,则不会向下舍入。或long int li = 5435.56;向下舍入的含义是什么?其次,为什么会导致大数字值不正确?我认为long int和float具有相同的位数。

第3。 char加倍

char c = 130;
double x4 = c;
std::cout << x4 << std::endl;

为什么这会导致-126char c = 100;提供正确的值?

4。 int to char

int i = 200;
char x5 = i;
std::cout << x5 << std::endl;

这不打印任何内容(无输出)。为什么?我认为最多255个结果应该是正确的,因为char可以存储最多255个值。

4 个答案:

答案 0 :(得分:3)

编辑:每个帖子都有一个问题。在这里,我回答#3和#4

  

我认为最多255个结果应该是正确的,因为char可以存储最多255个值。

这是一个不正确的假设。 (Demo

如果char被签名且8位(1字节),则有潜在的有符号溢出。它的最大值只有127.这将是未定义的行为。

char是否已签名是依赖于实现的,但通常是。它总是长1个字节,但允许“1字节”依赖于实现,尽管它几乎普遍是8位。

事实上,如果您引用任何ASCII表,在进入“扩展”ASCII之前它只会达到127,在大多数平台上,您需要一个宽字符类型才能显示它。

所以#3和#4中的代码溢出了。 当您尝试char c = 130

时,您甚至应该收到警告
  

警告:隐式常量转换溢出

答案 1 :(得分:3)

  1. 浮点数通常没有足够的精度来完全表示5543444.76。您的float可能会存储值5543455.0。对int的强制转换不是舍入发生的地方。从浮点到int的转换总是截断小数。尝试使用double代替float或直接将值分配给int来说明差异。

  2. 许多float位用于表示符号和指数,它无法准确表示所有int的相同大小。同样,这是精度问题,必须丢弃最低有效数字,从而导致看起来像舍入误差的意外结果。考虑科学记数法。您可以使用少量数字表示非常大范围的值,但只跟踪几个小数点。删除不太重要的数字。

  3. char可能已签名或未签名,具体取决于您的平台。似乎char在您的平台上签名为8位,这意味着它只能表示-128到127之间的值,显然130超过了该限制。由于未定义有符号整数溢出,因此您的测试用例可能会执行任何操作,包括换行到-126。

  4. char个变量在传递给std::cout时不会打印其值。它们打印与该值相关联的字符。见this table。请注意,由于值200超出了char在您的平台上可以表示的最大值,因此它可能会执行任何操作,包括尝试显示没有明显表示的字符。

答案 2 :(得分:2)

  1. float只有23位精度。 5543444不适合23位,因此它会四舍五入到最接近的值。

  2. 您有未初始化的li,因此它是未定义的行为。也许您应该编辑问题以显示您想知道的真实代码。

  3. char经常签名。 130不能表示为签名char。这可能是未定义的行为(必须检查标准以确定,它可能是实现定义的,或者可能有一些特殊规则),但在PC CPU的实践中,编译器采用130的最低位为130并显示它们进入8位有符号字符,并设置第8位,产生负值。

  4. 与上面的3相同:200不适合您的char签名的8位整数。相反,它最终会设置符号位,从而产生负值。

答案 3 :(得分:2)

  1. 距离5,543,444.76最近的IEEE 754 32位浮点数可以表示为5,543,445.0。见this IEEE 754 converter。因此f等于5543445.0f,然后在转换为整数时向下舍入为5543445

  2. 即使在您的特定系统上,floatlong int可能具有相同的大小,但是一个中的所有值都不能由另一个表示。例如,0.5f无法表示为long int。同样,100000002不能表示为float:最近的IEEE 754 32位浮点数为100000000.0f100000008.0f。 通常,您需要阅读有关floattng点表示的信息。 Wikipedia是个不错的开始。

  3. 根据您所使用的系统,
  4. char可能是signed charunsigned char。在(8位)signed char案例中,{{1}无法表示。发生有符号整数溢出(即UB),最有可能包含-126(注意130 + 126 = 256)。另一方面,100是130的完全有效值。

  5. Extended ASCII Table中,200张地图为signed char。如果您的系统没有处理扩展的ascii(例如,如果它配置了UTF-8),或者如果您没有字体来表示此字符,那么您将看不到输出。如果您使用È定义为char的系统,则无论如何都是UB。