将 DBL_MAX 转换为 int 的结果不同于 std::<double>numeric_limits::max() 到 int
results from convert DBL_MAX to int is different from std::numeric_limits<double>::max() to int
在做转换测试时,我在c++中遇到一些奇怪的行为。
<<h2>上下文/h2>在线c++参考表明,std::numeric_limits<double>::max()
(定义在limit.h
中)的返回值应该是DBL_MAX
(定义在float.h
中)。在我的测试中,当我打印出这些值时,两者确实完全相同。然而,当我把它们从double
转换到int
时,奇怪的事情出现了。
相同的输入,不同的结果?
int32_t t1 = (int) std::numeric_limits<double>::max();
设置t1
为INT_MIN
, int32_t t2 = (int) DBL_MAX;
设置t2
为INT_MAX
。当使用static_cast<int>
进行强制转换时也是如此。
相同的输入,相同的结果在类似的情况下
但是,如果我定义一个函数int32_t doubleToInt(double dvalue) {
return (int) value;
}
doubleToInt(std::numeric_limits<double>::max())
和doubleToInt(DBL_MAX)
都返回INT_MIN
。
为了帮助理解,我用Java实现了一个类似的程序。在这里,所有类型转换都返回INT_MAX
的值,无论是否在函数中。
谁能指出为什么在c++中结果在某些情况下是INT_MIN
,而在其他情况下是INT_MAX
?在c++中,当将DBL_MAX
转换为int
时,预期的行为应该是什么?
c++示例代码
#include <iostream>
#include <limits>
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
template <typename T, typename D> D cast(T a, D b) { return (D) a;}
int main()
{
int32_t t1 = 9;
std::cout << std::numeric_limits<double>::max() << std::endl;
std::cout << DBL_MAX << std::endl;
std::cout << (int32_t) std::numeric_limits<double>::max() << std::endl;
std::cout << (int32_t) DBL_MAX << std::endl;
std::cout << cast(std::numeric_limits<double>::max(), t1) << std::endl;
std::cout << cast(DBL_MAX, t1) << std::endl;
return 0;
}
为了完整:我使用cygwin gcc和java 8
尝试将大于INT_MAX
的浮点数转换为int
是未定义的行为:
浮点型的右值可以转换为整型的右值。转换截断;也就是说,小数部分被丢弃。如果截断的值不能为,则行为未定义以目标类型表示。(§4.9, para;1)
因此编译器可以为转换生成任何值(甚至可以做其他事情,例如抛出异常)。不同的编译器可以做不同的事情。同一个编译器可以在不同的时间做不同的事情。
试图理解为什么未定义行为的特定实例会显示它所显示的结果是没有真正意义的(除非您试图对编译器进行反向工程,即使这样UB通常也不是特别有趣)。相反,您需要专注于避免未定义的行为。
例如,由于任何浮点值到整数的范围外强制转换都是未定义的,因此您需要确保此类强制转换不涉及范围外值。与其他一些语言不同[注1],c++标准不提供易于识别的可测试的结果,因此您需要在进行强制转换之前进行测试。
注意DBL_MAX
是一个宏,它的替换是一个表示最大可表示浮点数近似值的字符串。另一方面,std::numeric_limits<double>::max()
是精确的最大可表示浮点数。
差异通常不应该是明显的,但是(正如标准& section;5.20 [expr]中的注释所指出的那样)。Const],第6段):
由于本国际标准对浮点运算的精度没有限制,因此在翻译过程中对浮点表达式求值是否与在程序执行过程中对相同表达式(或对相同值进行相同操作)求值产生相同的结果是未指定的。
虽然std::numeric_limits<double>::max()
被声明为constexpr
,但是转换为int
的不是常量表达式(根据& section;5.20/p2.5),因为它的行为是未定义的。
指出
- 例如,在Java中,转换定义得很好。有关详细信息,请参阅Java语言规范。
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 'short int'持有的值溢出,但"自动"不会溢出?
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 调用'begin(int [n])'没有匹配函数
- 没有显式声明的int[]中的foreach
- 在c++中访问int到类对象的映射时出错
- 为什么我无法更改"set<set>"循环中的值<int>
- EASTL矢量<向量<int>>连续的
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- 'structstd::对<int,int>'没有名为'push_back'