整数和浮点数转换
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;
为什么 -126
而 char 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
float 只有 23 位精度。 5543444 不适合 23 位,因此它会四舍五入到最接近的值。
您未初始化 li
,因此这是未定义的行为。也许你应该编辑问题以显示你想知道的真实代码。
char
经常被签名。 130 不能表示为有符号 char
。这可能是未定义的行为(必须检查标准才能确定,它可能是实现定义的或者可能有一些特殊规则),但实际上在 PC CPU 上,编译器采用130 并将它们显示为 8 位带符号字符,并设置第 8 位,结果为负值。
与上面的 3 相同:200 不适合带符号的 8 位整数,而您的 char
可能是。相反,它最终设置了符号位,导致负值。
浮点数通常没有足够的精度来完全表示 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
在您的平台上可以表示的最大值,它可能会做任何事情,包括尝试显示一个没有明显表示的字符。
IEEE 754 32 位浮点数可以表示的最接近 5,543,444.76 的数字是 5,543,445.0。参见 this IEEE 754 converter。所以 f
等于 5543445.0f
然后在转换为整数时向下舍入为 5543445
即使在您的特定系统上 float
和 long int
可能具有相同的大小,一个的所有值都不能由另一个表示。例如,0.5f
不能表示为 long int
。同样,100000002
不能表示为 float
:最接近的 IEEE 754 32 位浮点数是 100000000.0f
和 100000008.0f
.
通常,您需要阅读有关浮点表示的信息。 Wikipedia 是一个好的开始。
根据您所在的系统,char
可能是 signed char
或 unsigned char
。在(8 位)signed char
的情况下,130
无法表示。发生有符号整数溢出(即 UB)并且很可能它换行到 -126(请注意 130+126=256)。另一方面,100 是 signed char
.
的完全有效值
在Extended ASCII Table中,200映射到È
。如果您的系统不处理扩展的 ascii(例如,如果它配置为 UTF-8)或者如果您没有字体来表示这个字符,您将看不到任何输出。如果您在 char
定义为 signed char
的系统上,无论如何它都是 UB。
我在 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;
为什么 -126
而 char 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
float 只有 23 位精度。 5543444 不适合 23 位,因此它会四舍五入到最接近的值。
您未初始化
li
,因此这是未定义的行为。也许你应该编辑问题以显示你想知道的真实代码。char
经常被签名。 130 不能表示为有符号char
。这可能是未定义的行为(必须检查标准才能确定,它可能是实现定义的或者可能有一些特殊规则),但实际上在 PC CPU 上,编译器采用130 并将它们显示为 8 位带符号字符,并设置第 8 位,结果为负值。与上面的 3 相同:200 不适合带符号的 8 位整数,而您的
char
可能是。相反,它最终设置了符号位,导致负值。
浮点数通常没有足够的精度来完全表示
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
在您的平台上可以表示的最大值,它可能会做任何事情,包括尝试显示一个没有明显表示的字符。
IEEE 754 32 位浮点数可以表示的最接近 5,543,444.76 的数字是 5,543,445.0。参见 this IEEE 754 converter。所以
f
等于5543445.0f
然后在转换为整数时向下舍入为5543445
即使在您的特定系统上
float
和long int
可能具有相同的大小,一个的所有值都不能由另一个表示。例如,0.5f
不能表示为long int
。同样,100000002
不能表示为float
:最接近的 IEEE 754 32 位浮点数是100000000.0f
和100000008.0f
.
通常,您需要阅读有关浮点表示的信息。 Wikipedia 是一个好的开始。
根据您所在的系统,char
可能是signed char
或unsigned char
。在(8 位)signed char
的情况下,130
无法表示。发生有符号整数溢出(即 UB)并且很可能它换行到 -126(请注意 130+126=256)。另一方面,100 是signed char
. 的完全有效值
在Extended ASCII Table中,200映射到
È
。如果您的系统不处理扩展的 ascii(例如,如果它配置为 UTF-8)或者如果您没有字体来表示这个字符,您将看不到任何输出。如果您在char
定义为signed char
的系统上,无论如何它都是 UB。