整数和浮点数转换

Integer and float conversions

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

1.浮动到 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 到 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 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 个值。

编辑:请按 post 提出一个问题。这里我回答 #3 和 #4

I think up to 255 the result should be correct because char can store values up to 255.

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

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

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

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

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

时,您甚至应该得到警告

warning: overflow in implicit constant conversion

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

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

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

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

  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 在您的平台上可以表示的最大值,它可能会做任何事情,包括尝试显示一个没有明显表示的字符。

  1. IEEE 754 32 位浮点数可以表示的最接近 5,543,444.76 的数字是 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.
    通常,您需要阅读有关浮点表示的信息。 Wikipedia 是一个好的开始。

  3. 根据您所在的系统,
  4. char 可能是 signed charunsigned char。在(8 位)signed char 的情况下,130无法表示。发生有符号整数溢出(即 UB)并且很可能它换行到 -126(请注意 130+126=256)。另一方面,100 是 signed char.

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