整数和浮点数转换
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;
为什么这会导致-126
而char 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
。
即使在您的特定系统上,float
和 long int
的大小可能相同,但其中一个的所有值不能由另一个表示。例如,0.5f
不能表示为 long int
。同样,100000002
不能表示为 float
:最接近的 IEEE 754 32 位浮点数是 100000000.0f
和 100000008.0f
。
通常,您需要阅读有关 floattng 点表示的信息。 Wikipedia 是一个好的开始。
char
可能是signed char
或unsigned char
,具体取决于您所在的系统。在(8 位)signed char
的情况下,130
无法表示。发生有符号整数溢出(即 UB),并且很可能会换行到 -126(注意 130+126=256)。另一方面,对于signed char
,100 是一个完全有效的值。
在Extended ASCII Table 中,200 映射到È
。如果您的系统没有处理扩展 ascii(例如,如果它配置了 UTF-8)或者如果您没有字体来表示这个字符,您将看不到任何输出。如果您在一个将char
定义为signed char
的系统上,无论如何它都是UB。
【讨论】:
以上是关于整数和浮点数转换的主要内容,如果未能解决你的问题,请参考以下文章