Rumah  >  Artikel  >  pembangunan bahagian belakang  >  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
Barbara Streisandasal
2024-11-04 21:38:02744semak imbas

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;

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;

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>

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!

Kenyataan:
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