大家应该都知道浮点数存在精度问题,所以问题就来了,我如何才能判断两个数是否近似相等,或者某个浮点数是否为0。
其实这是一个问题,对于前者,我们需要二者作差,然后与0进行比较。这样前者与后者就是同一个问题了,即如何判断某个浮点数是否为0。我所知道的比较简单但是不是很好的方法就是使用1e-7或者更小的数,如下所示(以单精度为例):
#include <iostream>
#include <cfloat>
using namespace std;
int main()
{
float num;
cout << "输入一个数:";
cin >> num;
if (num < 1e-7 && num > -1e-7)
cout << num << "近似为0" << endl;
else
cout << num << "不近似为0" << endl;
return 0;
}
上述方式以C++代码为例。由于不同编程语言有不同的处理方式,大家可以不限制使用任何编程语言。当然,如果您有更通用的方式当然再好不过了。
얼마나 작은지 "충분히 작은지"는 다루고 있는 특정 문제에 따라 결정되어야 합니다. 예를 들어
double
을 사용하여 금액을 표현한다면1e-4
은 0으로 간주될 수 있습니다. 그리고 과학적인 계산을 하면1e-7
이 여전히 너무 클 것 같습니다.<cfloat>
은DBL_EPSILON
을1.0
과 가장 가까운 차이점으로 정의합니다. 여기를 참조하세요.부동소수점 수의 비교는 여전히 실제 저장 규칙을 기반으로 해야 합니다. 왜냐하면 부동소수점 수는 이진수로 저장되며, 이진수를 사용하여 소수를 표현하는 것은 정확하게 표현할 수 없기 때문입니다. 포인트 숫자가 상대적으로 작으면 을 이진수로 정확하게 표현하는 것이 불가능할 수 있습니다. 왜? 먼저 부동 소수점 숫자의 소수점 이하 자릿수를 이진수로 표현하면 다음과 같습니다.
출력: 0.30000001192092896소수점 1자리: 0.5(2^-1)
소수점 2자리: 0.25(2^-2)
.. .
N 소수 자릿수: 2^-n
즉,
부동 소수점 숫자의 소수 부분은 2^-1...2^-n으로 구성됩니다. , 유효 숫자가 적은 부동 소수점 숫자를 정확하게 표현할 수 없는 이유를 이해할 수 있습니다. 예를 들어, 위의 숫자 조합으로 0.3을 정확하게 표현할 수 없다면 다음을 시도해 보세요. 으아아아
0.3을 0.5로 바꾸면 괜찮습니다. 0.5는 2^-1로 정확하게 표현할 수 있기 때문입니다! 마찬가지로 0.625도 괜찮습니다.
원래 포스터의 질문으로 돌아가서: 0.3 == 0.3을 직접 판단하면 문제가 없습니다. 같은 숫자는 같은 표현이므로 '=='를 직접 사용할 수 있습니다. 특히 0과 같이 정확하게 표현할 수 있는 숫자인 경우에는 더욱 그렇습니다.그렇다면 왜 cout << 0.3을 직접 출력할 수 있을까요?
cout이 기본적으로 반올림을 수행하기 때문입니다.
그런데 0.1+0.2와 0.3이 같은지 판단하면 안 됩니다. 둘 다 정확도 손실이 있고, 손실 값도 다르기 때문에 직접 비교할 수 없고 사용해야 하기 때문입니다.
같은 방법이죠.
abs((0.1+0.2) - 0.3)<EPSILON
부동 소수점 숫자(float 또는 double 유형)의 컴퓨터 표현에는 정밀도 제한이 있습니다. 정밀도 제한을 초과하는 부동 소수점 숫자의 경우 컴퓨터는 정밀도를 초과하는 소수 부분을 자릅니다. 따라서 원래 같지 않은 두 부동 소수점 숫자가 컴퓨터에서는 동일해질 수 있습니다. 예:
으아아아