Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapa Kod Pembundaran Titik Terapung Saya Menghasilkan Keputusan Berbeza dengan Pengoptimuman Pengkompil Didayakan?

Mengapa Kod Pembundaran Titik Terapung Saya Menghasilkan Keputusan Berbeza dengan Pengoptimuman Pengkompil Didayakan?

Susan Sarandon
Susan Sarandonasal
2024-11-14 19:39:02906semak imbas

Why Does My Floating-Point Rounding Code Produce Different Results with Compiler Optimizations Enabled?

Ketaksamaan Pembundaran Titik Terapung dengan Pengoptimuman Didayakan: Pepijat Pengkompil atau Dilema Pengoptimuman?

Pengiraan titik terapung selalunya boleh menunjukkan tingkah laku yang tidak dijangka, terutamanya apabila pengoptimuman pengkompil didayakan. Pertimbangkan coretan kod berikut:

#include <cstdlib>
#include <iostream>
#include <cmath>

double round(double v, double digit)
{
    double pow = std::pow(10.0, digit);
    double t = v * pow;
    double r = std::floor(t + 0.5);
    return r / pow;
}

int main()
{
    std::cout << round(4.45, 1) << std::endl;
    std::cout << round(4.55, 1) << std::endl;
}

Output yang dijangkakan:

4.5
4.6

Walau bagaimanapun, apabila kod ini disusun menggunakan g dengan pengoptimuman (O1 - O3), output menjadi:

4.5
4.5

Punca Perbezaan:

Ketidakkonsistenan ini berpunca daripada fakta bahawa pemproses x86 secara dalaman menggunakan ketepatan lanjutan 80-bit untuk pengiraan titik terapung. Walau bagaimanapun, pembolehubah berganda biasanya lebar 64-bit. Apabila nilai titik terapung disimpan daripada daftar CPU ke memori, ia dibundarkan daripada ketepatan 80-bit kepada ketepatan 64-bit. Pembundaran ini boleh memperkenalkan sedikit ralat.

Kesan Tahap Pengoptimuman:

Tahap pengoptimuman yang berbeza boleh menjejaskan kekerapan nilai titik terapung disimpan ke dalam ingatan. Dengan tahap pengoptimuman yang lebih tinggi, ini berlaku lebih kerap. Akibatnya, ralat pembundaran menjadi lebih ketara.

Penyelesaian:

  1. Gunakan Pilihan GCC -ffloat-store: Ini pilihan mengarahkan pengkompil untuk menyimpan pembolehubah titik terapung dalam ingatan dan bukannya daftar. Ini memaksa pembundaran berlaku secara konsisten merentas tahap pengoptimuman yang berbeza.
  2. Gunakan double long Jenis: long double biasanya 80-bit lebar pada g . Menggunakan jenis ini boleh mengelakkan isu pembundaran sepenuhnya.
  3. Ubah suai Storan Pembolehubah: Simpan hasil pengiraan perantaraan ke dalam pembolehubah untuk meminimumkan ralat pembundaran.

Pertimbangan Selanjutnya:

  • Binaan Intel x86_64 kurang terjejas oleh isu ini kerana pengkompil menggunakan daftar SSE untuk apungan dan berganda secara lalai, menghapuskan keperluan untuk ketepatan lanjutan.
  • - Pilihan pengkompil mfpmath boleh digunakan untuk mengawal ketepatan titik terapung yang digunakan dalam binaan x86_64.
  • Sama ada untuk sentiasa menghidupkan pilihan -float-store bergantung pada aplikasi khusus dan kepekaannya terhadap ketepatan titik terapung. Untuk aplikasi kritikal, mungkin bijak untuk menggunakan pilihan ini untuk memastikan hasil yang konsisten.
  • Menyiasat kod C dan perpustakaan sedia ada untuk isu yang berpotensi boleh memakan masa. Pertimbangkan untuk menggunakan alatan atau melaksanakan ujian untuk mengesan dan menangani sebarang masalah ketepatan titik terapung.

Atas ialah kandungan terperinci Mengapa Kod Pembundaran Titik Terapung Saya Menghasilkan Keputusan Berbeza dengan Pengoptimuman Pengkompil Didayakan?. 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