大家应该都知道浮点数存在精度问题,所以问题就来了,我如何才能判断两个数是否近似相等,或者某个浮点数是否为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++代码为例。由于不同编程语言有不同的处理方式,大家可以不限制使用任何编程语言。当然,如果您有更通用的方式当然再好不过了。
Seberapa kecil "cukup kecil" harus ditentukan oleh masalah khusus yang ditangani. Contohnya, jika anda menggunakan
double
untuk menyatakan jumlah,1e-4
boleh dianggap sifar. Dan jika kita melakukan pengiraan saintifik, saya takut1e-7
masih terlalu besar.<cfloat>
mentakrifkanDBL_EPSILON
sebagai perbezaan yang paling hampir kepada1.0
. Lihat di sini.Perbandingan nombor titik terapung masih perlu berdasarkan peraturan storan sebenar, kerana nombor titik terapung disimpan dalam perduaan, dan menggunakan perduaan untuk mewakili perpuluhan tidak boleh diwakili dengan tepat Walaupun nombor titik terapung mempunyai perpuluhan yang lebih sedikit digit bererti, maka Ia mungkin tidak mungkin untuk mewakili dengan tepat dalam perduaan. kenapa?
Pertama sekali, perwakilan binari tempat perpuluhan nombor titik terapung adalah seperti berikut:
1 tempat perpuluhan: 0.5 (2^-1)
2 tempat perpuluhan: 0.25 (2^-2)
.. .
N tempat perpuluhan: 2^-n
Maksudnya, bahagian perpuluhan mana-mana nombor titik terapung terdiri daripada 2^-1...2^-n , supaya anda boleh memahami mengapa nombor titik terapung dengan beberapa digit bererti tidak boleh dinyatakan dengan tepat Contohnya, 0.3 tidak boleh dinyatakan dengan tepat menggunakan gabungan digit di atas Jika anda tidak percaya cout, cuba:
Output: 0.30000001192092896
Dan jika anda menggantikan 0.3 dengan 0.5, itu tidak mengapa, kerana 0.5 boleh diwakili dengan tepat oleh 2^-1! Dengan cara yang sama, 0.625 juga OK.
Lalu mengapa kita biasanya boleh mengeluarkan 0.3 secara langsung apabila cout << Ini kerana cout melakukan pembundaran secara lalai .
Kembali kepada soalan poster asal: Jika anda menilai secara langsung 0.3 == 0.3, maka tiada masalah, kerana nombor yang sama mempunyai perwakilan yang sama, jadi anda boleh menggunakan '==' secara langsung. Ini benar terutamanya jika ia adalah nombor yang boleh diwakili dengan tepat, seperti 0.
Tetapi jika anda menilai sama ada 0.1+0.2 dan 0.3 adalah sama, itu tidak akan berfungsi, kerana kedua-duanya mempunyai kehilangan ketepatan, dan nilai kerugian berbeza, jadi anda tidak boleh membandingkan secara langsung dan anda perlu menggunakan kaedah seperti
abs((0.1+0.2) - 0.3)<EPSILON
.Perwakilan komputer bagi nombor titik terapung (jenis terapung atau berganda) mempunyai had ketepatan Untuk nombor titik terapung yang melebihi had ketepatan, komputer akan memotong bahagian perpuluhan melebihi ketepatannya. Oleh itu, dua nombor titik terapung yang asalnya tidak sama mungkin menjadi sama dalam komputer. Contohnya: