关于一个float型的数警告机制的问题?

中才德创 2009-04-10 06:10:27
// 关于一个float型的数警告机制的问题?
//
#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
float f0 = 3.0;
//ok

float f1 = 3.1;
//warning C4305: 'initializing' : truncation from 'double' to 'float'


float f2 = 3.2;
//warning C4305: 'initializing' : truncation from 'double' to 'float'


float f3 = 3.3;
//warning C4305: 'initializing' : truncation from 'double' to 'float'

float f4 = 3.4;
//warning C4305: 'initializing' : truncation from 'double' to 'float'

float f5 = 3.5;
//ok

float f6 = 3.6;
//warning C4305: 'initializing' : truncation from 'double' to 'float'

return 0;
}

// 一个n.m这样写法的数,默认为double型的数.所以才出现truncation from 'double' to 'float'.
// 因此,通行的写法是float f = 1.2f;尾随一个符号f.
// 但为什么f0 = 3.0;f5 = 3.5;却是ok的?是警告机制做得不完美?
...全文
157 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jarrys 2009-04-10
  • 打赏
  • 举报
回复
还真学习了。。
bfhtian 2009-04-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 geochway 的回复:]
由于精度所限,double也许能够精确地表示3.1,3,6,3.2等,但float却不能.
但3.0,3.5都可以用double,float精确表示,因此不存在截短的问题.

可以用下面的代码测试一下:
double x30=3.0,x31=3.1,x35=3.5,x36=3.6;
float f30=3.0,f31=3.1,f35=3.5,f36=3.6;
bool b30=(x30==f30),b31=(x31==f31),b35=(x35==f35),b36=(x36==f36);

结果应该是b30,b35为真,b31,b36为假.
[/Quote]
嗯,和存储方式有关系,可以看下组成原理
  • 打赏
  • 举报
回复
...好有测试精神
ForestDB 2009-04-10
  • 打赏
  • 举报
回复
首先你写的字面上的浮点数如果不带f后缀,都是认为是double类型的,然后不是所有的浮点数都能精准的用二进制表示的,可以参看IEEE的标准。
所谓double和float都是浮点数,只是精度不一样而已。
对于3.0,3.5这样的数编译器根据IEEE的标准认为该数可以用二进制精确表示,然后从double转float的时候只是指数位减少,不存在精度问题,即不存在truncate的问题,但3.1这样的编译器认为转换会缺失精度,所以警告你了。
你可以试试3.75这样的数,应该没警告^^。
beyond071 2009-04-10
  • 打赏
  • 举报
回复
呵呵 学习了
中才德创 2009-04-10
  • 打赏
  • 举报
回复
double x30 = 3.0;// 00 00 00 00 00 00 08 40
double x31 = 3.1;// cd cc cc cc cc cc 08 40
double x35 = 3.5;// 00 00 00 00 00 00 0c 40
double x36 = 3.6;// cd cc cc cc cc cc 0c 40
float f30 = 3.0f;// 00 00 40 40
float f31 = 3.1f;// 66 66 46 40
float f35 = 3.5f;// 00 00 60 40
float f36 = 3.6f;// 66 66 66 40
bool b30 = (x30==f30);// true
bool b31 = (x31==f31);// false
bool b35 = (x35==f35);// true
bool b36 = (x36==f36);// false

从上面的红色的00上推测,"对于3.0,3.5这样的数编译器根据IEEE的标准认为该数可以用二进制精确表示"是很有道理的。
有时报警,有时不报,让人很迷糊的。现在清楚很多了。
geochway 2009-04-10
  • 打赏
  • 举报
回复
再补充一句,IEEE标准中float和double在内部表达形式上是一致的,
只是指数的范围和尾数的范围不同,转换是非常简单的(截短),如果被
截掉的部分都是0,那就说明二者相等,反之说明有舍入误差.
geochway 2009-04-10
  • 打赏
  • 举报
回复
由于精度所限,double也许能够精确地表示3.1,3,6,3.2等,但float却不能.
但3.0,3.5都可以用double,float精确表示,因此不存在截短的问题.

可以用下面的代码测试一下:
double x30=3.0,x31=3.1,x35=3.5,x36=3.6;
float f30=3.0,f31=3.1,f35=3.5,f36=3.6;
bool b30=(x30==f30),b31=(x31==f31),b35=(x35==f35),b36=(x36==f36);

结果应该是b30,b35为真,b31,b36为假.

arong1234 2009-04-10
  • 打赏
  • 举报
回复
你观察倒是很仔细,但是个人觉得纠缠在这种鸡毛蒜皮的事情上完全是浪费时间,即使你找到答案,得到的好处又在哪里?不是每个问题的答案都是有价值的。也许只是编译器bug,如果你发现这是答案又怎样?

64,696

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧