Pertanyaan Perbandingan titik mengambang [duplikat]


Pertanyaan ini sudah memiliki jawaban di sini:

int main()
{
    float a = 0.7;
    float b = 0.5;
    if (a < 0.7)
    {
       if (b < 0.5) printf("2 are right");
       else         printf("1 is right");
    }
    else printf("0 are right");
}

Saya mengharapkan hasil dari kode ini 0 are right. Tapi saya cemas hasilnya 1 is right Mengapa?


61
2017-08-10 13:01


asal


Jawaban:


int main()
{
    float a = 0.7, b = 0.5; // These are FLOATS
    if(a < .7)              // This is a DOUBLE
    {
      if(b < .5)            // This is a DOUBLE
        printf("2 are right");
      else
        printf("1 is right");
    }
    else
      printf("0 are right");
}

Floats dipromosikan menjadi ganda selama perbandingan, dan karena pelampung kurang tepat daripada ganda, 0,7 sebagai pelampung tidak sama dengan 0,7 sebagai dua kali lipat. Dalam hal ini, 0,7 sebagai pelampung menjadi lebih rendah dari 0,7 sebagai ganda ketika dipromosikan. Dan seperti kata Christian, 0,5 menjadi kekuatan 2 selalu diwakilkan dengan tepat, jadi tes bekerja seperti yang diharapkan: 0.5 < 0.5 salah.

Jadi:

  • Perubahan float untuk double, atau:
  • Perubahan .7 dan .5 untuk .7f dan .5f,

dan Anda akan mendapatkan perilaku yang diharapkan.


129
2017-08-10 13:06



Masalahnya adalah bahwa konstanta yang Anda bandingkan adalah double tidak float. Juga, mengubah konstanta Anda menjadi sesuatu yang mudah digambarkan seperti faktor 5 akan membuatnya berkata 0 is right. Sebagai contoh,

main()
{
    float a=0.25,b=0.5; 
    if(a<.25) 
       {
       if(b<.5) 
               printf("2 are right");
       else
               printf("1 is right");
       }
else
printf("0 are right");
}

Keluaran:

0 are right

Pertanyaan SO ini Cara Paling Efektif untuk mengapung dan pembandingan ganda mencakup topik ini.

Juga, artikel ini di cygnus tentang perbandingan angka titik mengambang memberi kami beberapa kiat:

The float IEEE dan format ganda dirancang sehingga angka-angka   adalah "leksikografis memerintahkan", yang - dalam kata-kata IEEE   arsitek William Kahan berarti "jika dua angka floating-point di   format yang sama dipesan (katakanlah x <y), maka mereka diperintahkan sama   cara ketika bit mereka ditafsirkan sebagai integer Sign-Magnitude. "

Ini berarti bahwa jika kita mengambil dua mengapung dalam memori, tafsirkan sedikit mereka   pola sebagai bilangan bulat, dan membandingkannya, kita bisa tahu mana yang lebih besar,   tanpa melakukan perbandingan titik apung. Di dalam bahasa C / C ++ ini   perbandingan terlihat seperti ini:

if (*(int*)&f1 < *(int*)&f2)

Sintaks yang menawan ini berarti mengambil alamat f1, memperlakukannya sebagai   pointer integer, dan dereference-nya. Semua operasi penunjuk terlihat   mahal, tetapi pada dasarnya mereka semua membatalkan dan hanya berarti 'mengobati f1   sebagai bilangan bulat '. Karena kami menerapkan sintaks yang sama untuk f2 seluruh baris   berarti ‘bandingkan f1 dan f2, menggunakan representasi di memori mereka   diartikan sebagai bilangan bulat alih-alih pelampung ’.


14
2017-08-10 13:14



Ini karena masalah pembulatan sementara mengkonversi dari pelampung menjadi dua kali lipat


3
2017-08-10 13:14



Umumnya membandingkan kesetaraan dengan pelampung adalah bisnis yang berbahaya (yang secara efektif apa yang Anda lakukan saat Anda membandingkan tepat pada batas>), ingat bahwa dalam pecahan desimal tertentu (seperti 1/3) tidak dapat diungkapkan dengan tepat, hal yang sama dapat dikatakan tentang biner,

0.5= 0.1, akan sama di float atau double.

0.7=0.10110011001100 dll selamanya, 0,7 tidak bisa persis diwakili dalam biner, Anda mendapatkan kesalahan pembulatan dan mungkin (sangat sedikit) berbeda antara float dan double

Perhatikan bahwa pergi antara mengapung dan menggandakan Anda memotong sejumlah tempat desimal yang berbeda, maka hasil Anda tidak konsisten.


2
2018-04-05 13:44



Juga, btw, Anda memiliki kesalahan dalam logika Anda 0 benar. Anda tidak memeriksa b saat Anda menghasilkan 0 benar. Tetapi semuanya sedikit misterius dalam apa yang sebenarnya ingin Anda capai. Perbandingan titik mengambang antara pelampung dan ganda akan memiliki variasi, menit, jadi Anda harus membandingkan dengan variasi 'diterima' delta untuk situasi Anda. Saya selalu melakukan ini melalui fungsi inline yang hanya melakukan pekerjaan (melakukannya sekali dengan makro, tapi itu terlalu berantakan). Bagaimanapun, yah, masalah pembulatan penuh dengan contoh seperti ini. Baca hal-hal floating point, dan ketahuilah bahwa .7 berbeda dari .7f dan menugaskan .7 ke float akan melontarkan double ke float, sehingga mengubah sifat nilai yang tepat. Tapi, asumsi pemrograman tentang b menjadi salah karena Anda memeriksa sebuah teriakan kepada saya, dan saya harus mencatat bahwa :)


0
2017-08-10 16:07