Rumah > pembangunan bahagian belakang > C++ > Mengapakah aritmetik titik terapung C menghasilkan keputusan yang tidak dijangka, dan bagaimanakah kita boleh mengurangkan anomali ketepatan ini?

Mengapakah aritmetik titik terapung C menghasilkan keputusan yang tidak dijangka, dan bagaimanakah kita boleh mengurangkan anomali ketepatan ini?

Barbara Streisand
Lepaskan: 2024-11-04 21:38:02
asal
827 orang telah melayarinya

Why does C   floating-point arithmetic produce unexpected results, and how can we mitigate these precision anomalies?

Anomali dan Resolusi Ketepatan Titik Terapung C

Walaupun penggunaannya meluas, nombor titik terapung dalam C mempamerkan had dalam ketepatan. Pertimbangkan coretan kod berikut:

<code class="cpp">double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;
Salin selepas log masuk

Kod ini mengeluarkan 0.2999999999999999889 dan bukannya 0.3 yang dijangkakan. Percanggahan ini berlaku kerana pembolehubah a tidak disimpan betul-betul sebagai nombor titik terapung berketepatan 0.3 tetapi lebih kepada anggarannya disebabkan oleh perwakilan terhingga nilai titik terapung.

Tingkah laku yang lebih mengejutkan timbul apabila a berulang kali ditambah 50 kali:

<code class="cpp">double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;
Salin selepas log masuk

Kod ini secara mengejutkan mengeluarkan 15.000000000000014211 dan bukannya 15.0. Ini kerana setiap penambahan mengumpul ralat anggaran, membawa kepada ralat terkumpul lebih besar daripada ketepatan asal.

Menyelesaikan Anomali Ketepatan

Untuk mendapatkan hasil yang tepat, ia adalah penting untuk mengelak daripada menetapkan ketepatan output lebih besar daripada digit yang tersedia untuk jenis berangka. Ini boleh dicapai menggunakan kelas std::numeric_limits:

<code class="cpp">#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}</code>
Salin selepas log masuk

Kod ini menggunakan fungsi ahli digit10 untuk menetapkan ketepatan kepada digit maksimum yang tersedia untuk nombor titik terapung berketepatan dua, iaitu 15 digit untuk dua kali ganda.

Had Aritmetik Titik Terapung

Walaupun penyelesaian yang disediakan meminimumkan ralat ketepatan, adalah penting untuk menyedari bahawa aritmetik titik terapung mempunyai had yang wujud. . Jika gelung melibatkan beribu-ribu lelaran, walaupun dengan ketepatan yang ditetapkan dengan sewajarnya, ralat terkumpul mungkin menjadi ketara. Dalam senario sedemikian, jenis data alternatif, seperti nombor titik tetap atau nombor rasional, mungkin lebih sesuai untuk mengekalkan nilai tepat.

Atas ialah kandungan terperinci Mengapakah aritmetik titik terapung C menghasilkan keputusan yang tidak dijangka, dan bagaimanakah kita boleh mengurangkan anomali ketepatan ini?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan