1

我使用std::chrono工具测量了几个时间差。我对 float 和 double 类型都进行了测试。结果令人惊讶。double 类型转到...00000007 位或...9999999之后,而 float 类型继续显示有效数字。

编码:

std::chrono::steady_clock::time_point Start, End;
std::chrono::duration<float, std::ratio<1, 1>> fDuration;
std::chrono::duration<double, std::ratio<1, 1>> dbDuration;
std::cout.precision(20);
std::cout << std::fixed;
for (DWORD dwSleepTime=0; dwSleepTime<=10000; dwSleepTime+=1000)
{
    Start = std::chrono::steady_clock::now();
    Sleep(dwSleepTime);
    End = std::chrono::steady_clock::now();
    fDuration = std::chrono::duration_cast<std::chrono::duration<float>>(End - Start);
    dbDuration = std::chrono::duration_cast<std::chrono::duration<double>>(End - Start);
    std::cout << "Time passed (float)  = " << fDuration.count()  << std::endl;
    std::cout << "Time passed (double) = " << dbDuration.count() << std::endl << std::endl;
}

它的输出:

Time passed (float)  = 0.00000000000000000000
Time passed (double) = 0.00000000000000000000

Time passed (float)  = 1.00005722045898440000
Time passed (double) = 1.00005720000000010000

Time passed (float)  = 2.00011444091796870000
Time passed (double) = 2.00011440000000020000

Time passed (float)  = 3.00017166137695310000
Time passed (double) = 3.00017159999999980000

Time passed (float)  = 4.00022888183593750000
Time passed (double) = 4.00022880000000040000

Time passed (float)  = 5.00028610229492190000
Time passed (double) = 5.00028600000000000000

Time passed (float)  = 6.00034332275390620000
Time passed (double) = 6.00034319999999970000

Time passed (float)  = 7.00040006637573240000
Time passed (double) = 7.00040040000000020000

Time passed (float)  = 8.00045776367187500000
Time passed (double) = 8.00045760000000070000

Time passed (float)  = 9.00051498413085940000
Time passed (double) = 9.00051479999999950000

Time passed (float)  = 10.00057220458984400000
Time passed (double) = 10.00057200000000000000

这种现象背后的原因是什么?在这种特殊情况下,双精度类型真的给出不太精确的结果吗?


我的系统:
IDE:Visiual Studio 2012
操作系统:Windows 7 x64
CPU:Intel i5 750

4

2 回答 2

3

double类型精确地表示值。因此,当您打印它们时,您会看到一个非常接近原始值的值。例如,当原始值为 1.0000572,然后将其转换为double时,结果为 1.000057200000000090511775852064602077007293701171875,因为这是double可以表示的最接近的值。

float类型表示值不太精确。当您转换 1.0000572 时,结果为 1.000057220458984375,因为这是接近float1.0000572 的结果。

此外,当您将这些转换为十进制以使用 Visual Studio 软件打印时,仅显示前 17 位数字,因为 Visual Studio 停在那里并将其余数字打印为零。(应该清楚的是,以这种方式打印它们并不意味着floatanddouble对象具有这些值。IEEE-754 浮点标准清楚地表明,所表示的确切值是我上面显示的值,1.000057220458984375 和1.000057200000000090511775852064602077007293701171875。高质量的软件可以根据要求将精确值打印到尽可能多的十进制数字。)

于 2013-08-04T14:04:36.017 回答
1

您想阅读有关二进制浮点和精度的信息!float有 6 个小数位的精度,double有 16 个小数位的精度(我想,但我一直记错确切的值;检查std::numeric_limits<T>::digits10)。由于二进制浮点不能精确地表示小数(只有一些但很多不是),打印二进制浮点值会导致在离开打印例程做它想做的事情时进行一些舍入。当您要求多位digits10数字时,通常会推迟舍入,并将实际的二进制小数值打印到您要求的任何位数。

在您上面描述的情况下,float版本刚刚开始打印实际值(可能有std::numeric_limits<T>::digits很多重要的地方)。该double版本似乎仍然合理,尽管要求 20 位数字已经将其放入应该/可以/可能显示近似值的区域。当然,这些都与std::chrono二进制浮点无关。

于 2013-08-04T13:47:06.427 回答