起因是一个求前后两个时间戳的中间值,简单的把两个时间戳相减再乘以一个比率(0.235)的事,但发现结果不对……算出来的新时间戳怎么比原先的较大时间戳的值还要大?!示例代码如下:
unsigned int end = 1678864370;
unsigned int begin = 1678864358;
float ratio = 0.235;
unsigned int result0 = begin + (end - begin) * ratio;
你们猜result0
这时的值是多少?竟然是1678864384!比end
还要大。目测是精度转换的问题,用以下代码测试一下:
#include <iostream>
using namespace std;
int main()
{
unsigned int end = 1678864370;
unsigned int begin = 1678864358;
float ratio = 0.235;
float floatNum = (end - begin) * ratio;
unsigned int result0 = begin + (end - begin) * ratio;
unsigned int result1 = begin + floatNum;
unsigned int result2 = begin + (int)floatNum;
unsigned int result3 = begin + (double)floatNum;
unsigned int result4 = begin + 2.81999993;
cout << result0 << endl;
cout << result1 << endl;
cout << result2 << endl;
cout << result3 << endl;
cout << result4 << endl;
}
编译器报了几个类似的警告:
ConsoleApplication1.cpp(10,23): warning C4244: “初始化”: 从“float”转换到“unsigned int”,可能丢失数据
最终输出:
1678864384
1678864384
1678864360
1678864360
1678864360
我当初想当然的以为unsinged int与float运算时,会都转成double后再进行运算,然而万万没想到会算出来奇怪的结果。据说编译器不同,转换方式会不一样,但这MSVC编译器算出来的结果也太离谱了吧!看来以后不同数据类型的运算,手动指定转换类型比较保险。
另外,float类型的最大值: 3.402823E+38,最小值: -3.402823E+38。float能保证6位有效数字,最多可表示7位,那么float只保存整型数据的话,最大能精确保存多大的数字呢?查了一大圈都没人说清楚。写个代码简单测试下吧
#include <iostream>
#include <format>
#include <string>
using namespace std;
int main()
{
/// float只保存整数,最大值
// 7位
cout << format("{} {}", __LINE__, float(1999999)) << endl; // yes
cout << format("{} {}", __LINE__, float(9999999)) << endl; // yes
// 8位
cout << format("{} {}", __LINE__, float(12345678)) << endl; // yes
cout << format("{} {}", __LINE__, float(18999990)) << endl; // yes
cout << format("{} {}", __LINE__, float(18999997)) << endl; // 18999996 no
cout << format("{} {}", __LINE__, float(1.8999997)) << endl; // yes
cout << format("{} {}", __LINE__, float(18999998)) << endl; // yes
cout << format("{} {}", __LINE__, float(18999999)) << endl; // 1.9e+07 no
cout << format("{} {}", __LINE__, float(19000001)) << endl; // 1.9e+07 no
cout << format("{} {}", __LINE__, float(19900001)) << endl; // 19900000 no
}
嗯……怎么说呢,以后大于6位数的整型数据就别用float存了,运算时也要注意类型转换。