Alo*_*ave 32

考虑的重要因素floatdouble数字是:
精确舍入


精度:
浮点数的精度是它可以表示的位数,而不会丢失它包含的任何信息.

考虑分数1/3.这个数字的十进制表示是0.33333333333333…3到无穷大.无限长数将需要无限存储与精确的精度来示出,但float还是double数据类型通常仅具有48字节.因此,浮点数和双数字只能存储一定数量的数字,其余数字必然会丢失.因此,没有明确准确的方法来表示浮点数或双数字,其数字需要比变量可以容纳更多的精度.


舍入:数字与数字
之间存在明显差异. 考虑分数.在,这可以很容易地表示为,并且可以被认为是易于表示的数字.但是,在二进制中,由无限序列表示:binarydecimal (base 10)
1/10decimal0.10.10.10.00011001100110011…

一个例子:

#include <iomanip>
int main()
{
    using namespace std;
    cout << setprecision(17);
    double dValue = 0.1;
    cout << dValue << endl;
}
Run Code Online (Sandbox Code Playgroud)

这个输出是:

0.10000000000000001
Run Code Online (Sandbox Code Playgroud)

并不是

0.1.
Run Code Online (Sandbox Code Playgroud)

这是因为双重必须截断近似值,因为它的内存有限,导致数字不完全正确0.1.这种情况称为舍入误差.


当比较两个密切float和double数字,例如舍入误差踢,最终比较产生不正确的结果,这是你永远不应该比较浮点数或双用的原因==.

你能做的最好的就是把它们区别开来并检查它是否小于epsilon.

abs(x - y) < epsilon
Run Code Online (Sandbox Code Playgroud)


Pra*_*ian 8

尝试运行此代码,结果会使原因显而易见.

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << std::setprecision(100) << (double)1.1 << std::endl;
  std::cout << std::setprecision(100) << (float)1.1 << std::endl;
  std::cout << std::setprecision(100) << (double)((float)1.1) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出:

1.100000000000000088817841970012523233890533447265625
1.10000002384185791015625
1.10000002384185791015625
Run Code Online (Sandbox Code Playgroud)

float不能也double不能准确地代表1.1.当您尝试进行比较时,浮点数会隐式上转换为double.double数据类型可以准确地表示float的内容,因此比较产生false.