整数和浮点数转换

Posted

技术标签:

【中文标题】整数和浮点数转换【英文标题】:Integer and float conversions 【发布时间】:2017-03-14 13:16:35 【问题描述】:

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

1.浮动到整数

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 li;
float x3 = li;
std::cout << x3 << std::endl;

一个练习的解决方案是对数值进行四舍五入,并导致大数字的值不正确。如果我尝试 long int li = 5435; 它不会向下舍入。还是long int li = 5435.56;向下取整的意思?其次,为什么它会导致大数的值不正确?我认为 long int 和 float 的位数相同。

3.字符加倍

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

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

4. int转char

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

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

【问题讨论】:

4.检查200的ASCII码.. 2.如果将浮点初始化为 int ,它将忽略小数部分。 在 1. 我不明白“用 float f = 5543444.76; 替换它”。那是已经存在的。你换什么? 大约 1/ IEEE 754 32 位浮点数可以表示的 5,543,444.76 中最接近的数字是 5,543,445.0。见this IEEE 754 converter。 一般来说,你需要阅读浮点表示法。 Wikipedia 是一个好的开始。 【参考方案1】:

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

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

这是一个错误的假设。 (Demo)

如果 char 有符号且 8 位(1 字节),则可能存在有符号溢出。它的最大值仅为 127。这将是未定义的行为。

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

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

所以你在#3 和#4 中的代码有溢出。 当你尝试char c = 130 时,你甚至应该得到一个警告:

警告:隐式常量转换溢出

【讨论】:

【参考方案2】:

    浮点数通常没有足够的精度来完全表示5543444.76。您的float 可能存储了值5543455.0。转换为 int 不是舍入发生的地方。从浮点转换为int 总是截断小数点。尝试使用double 而不是float 或将值直接分配给int 以说明区别。

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

    char 可能已签名或未签名,这取决于您的平台。 char 在您的平台上似乎是 8 位签名的,这意味着它只能表示从 -128 到 127 的值,显然 130 超出了该限制。由于未定义有符号整数溢出,您的测试用例可能会做任何事情,包括包装到 -126。

    char 变量在传递给 std::cout 时不会打印它们的值。他们打印与该值关联的字符。见this table。请注意,由于值 200 超过了 char 在您的平台上可以表示的最大值,它可能会做任何事情,包括尝试显示没有明显表示的字符。

【讨论】:

【参考方案3】:

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

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

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

    与上面的 3 相同:200 不适合带符号的 8 位整数,您的 char 可能是。相反,它最终设置了符号位,导致负值。

【讨论】:

【参考方案4】:

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

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

    char 可能是signed charunsigned char,具体取决于您所在的系统。在(8 位)signed char 的情况下,130 无法表示。发生有符号整数溢出(即 UB),并且很可能会换行到 -126(注意 130+126=256)。另一方面,对于signed char,100 是一个完全有效的值。

    在Extended ASCII Table 中,200 映射到È。如果您的系统没有处理扩展 ascii(例如,如果它配置了 UTF-8)或者如果您没有字体来表示这个字符,您将看不到任何输出。如果您在一个将char 定义为signed char 的系统上,无论如何它都是UB。

【讨论】:

以上是关于整数和浮点数转换的主要内容,如果未能解决你的问题,请参考以下文章

Python中整数和浮点数

Python中整数和浮点数

Python中整数和浮点数

整数和浮点数及运算函数

Linux上整数和浮点数的运算

SSE 整数与浮点数练习