查看这个简单的程序:
int main() {
float f2 = 7.2; // OK, with warning
float f3 = 7.199999809265137; // OK, no warning
float f4{ 7.2 }; // Fails
float f5{ 7.199999809265137 }; // OK, no warning
float f6 = { 7.2 }; // Fails
float f7 = { 7.199999809265137 }; // OK, no warning
}
使用默认选项(cl /W4
,版本19.00.23918)使用MSVC 2015进行编译时,收到以下消息:
FloatTest.cpp(2): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(4): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(4): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(6): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(6): warning C4305: 'initializing': truncation from 'double' to 'float'
该程序与Clang 3.0-3.8和GCC 4.5.4-6.1.0(使用http://melpon.org/wandbox测试)编译良好,仅对未使用的变量发出警告。此外,删除/注释掉行f4
和f6
会导致成功编译(只有行f2
的一个警告)。
最初看起来MSVC只是告诉我7.2不能精确地表示为float
,所以它是一个缩小的转换(在大括号初始化时是非法的)。但是,标准(draft N3337),第8.5.4节,注释7说明了这一点:
缩小转化是隐式转化......
- 从
long double
到double
或float
,或从double
到float
,除非源是常量表达式,转换后的实际值除外在可以表示的值范围内(即使它不能完全表示)
强调我的。由于7.2在float
可表示的值范围内,因此根据标准,其转换为float
不应是缩小转换。 MSVC在这里是错误的,我应该提交错误吗?
答案 0 :(得分:6)
#pragma float_control(precise, off, push)
float f2 = 7.2; // OK, with warning
//...
#pragma float_control(precise, pop)
答案 1 :(得分:-3)
某些浮点数可以用float
表示精确表示,有些则不能。如果数字可以x / 2^y
形式表示,其中x
是任何整数,而y
是23或更小的整数,则它适合。 大多数十进制数不能以这种方式表示,作为二进制数,它们永远重复。 7.2
就是一个例子。
您可以通过将f
附加到每个数字来轻松解决此问题,以向编译器表明这是float
常量,而不是double
。
float f4{ 7.2f };