['Jawaban yang benar' lebih menarik daripada memilih K
. Memilih K
akhirnya sama ad-hoc seperti memilih VISIBLE_SHIFT
tetapi memilih K
kurang jelas karena tidak seperti VISIBLE_SHIFT
itu tidak didasarkan pada properti tampilan. Jadi pilih racun Anda - pilih K
atau pilih VISIBLE_SHIFT
. Jawaban ini menganjurkan pemilihan VISIBLE_SHIFT
dan kemudian menunjukkan kesulitan dalam memilihK
]
Justru karena kesalahan bulat, Anda tidak boleh menggunakan perbandingan nilai 'tepat' untuk operasi logis. Dalam kasus spesifik Anda tentang posisi pada tampilan visual, tidak mungkin apakah posisi tersebut 0,0 atau 0,0000000003 - perbedaannya tidak terlihat oleh mata. Jadi logika Anda harus seperti:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
Namun, pada akhirnya, 'tidak terlihat oleh mata' akan tergantung pada properti tampilan Anda. Jika Anda dapat membatasi tampilan (Anda seharusnya bisa); lalu pilih VISIBLE_SHIFT
menjadi bagian dari batas atas itu.
Sekarang, 'jawaban yang benar' terletak di atas, K
jadi mari kita jelajahi memilih K
. 'Jawaban yang benar' di atas mengatakan:
K adalah konstanta yang Anda pilih sedemikian rupa sehingga akumulasi kesalahan perhitungan Anda pasti dibatasi oleh unit K di tempat terakhir (dan jika Anda tidak yakin Anda mendapatkan perhitungan batas kesalahan yang benar, buat K beberapa kali lebih besar dari apa yang perhitungan Anda katakan itu seharusnya)
Jadi kita butuh K
. Jika mendapatkan K
lebih sulit, kurang intuitif daripada memilih saya VISIBLE_SHIFT
maka Anda akan memutuskan apa yang cocok untuk Anda. Untuk menemukan K
kita akan menulis sebuah program pengujian yang terlihat pada sekelompokK
nilai sehingga kita dapat melihat bagaimana perilakunya. Seharusnya jelas bagaimana memilih K
, jika 'jawaban yang tepat' dapat digunakan. Tidak?
Kita akan menggunakan, sebagai rincian 'jawaban yang benar':
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Mari kita coba semua nilai K:
#include <math.h>
#include <float.h>
#include <stdio.h>
void main (void)
{
double x = 1e-13;
double y = 0.0;
double K = 1e22;
int i = 0;
for (; i < 32; i++, K = K/10.0)
{
printf ("K:%40.16lf -> ", K);
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
printf ("YES\n");
else
printf ("NO\n");
}
}
ebg@ebg$ gcc -o test test.c
ebg@ebg$ ./test
K:10000000000000000000000.0000000000000000 -> YES
K: 1000000000000000000000.0000000000000000 -> YES
K: 100000000000000000000.0000000000000000 -> YES
K: 10000000000000000000.0000000000000000 -> YES
K: 1000000000000000000.0000000000000000 -> YES
K: 100000000000000000.0000000000000000 -> YES
K: 10000000000000000.0000000000000000 -> YES
K: 1000000000000000.0000000000000000 -> NO
K: 100000000000000.0000000000000000 -> NO
K: 10000000000000.0000000000000000 -> NO
K: 1000000000000.0000000000000000 -> NO
K: 100000000000.0000000000000000 -> NO
K: 10000000000.0000000000000000 -> NO
K: 1000000000.0000000000000000 -> NO
K: 100000000.0000000000000000 -> NO
K: 10000000.0000000000000000 -> NO
K: 1000000.0000000000000000 -> NO
K: 100000.0000000000000000 -> NO
K: 10000.0000000000000000 -> NO
K: 1000.0000000000000000 -> NO
K: 100.0000000000000000 -> NO
K: 10.0000000000000000 -> NO
K: 1.0000000000000000 -> NO
K: 0.1000000000000000 -> NO
K: 0.0100000000000000 -> NO
K: 0.0010000000000000 -> NO
K: 0.0001000000000000 -> NO
K: 0.0000100000000000 -> NO
K: 0.0000010000000000 -> NO
K: 0.0000001000000000 -> NO
K: 0.0000000100000000 -> NO
K: 0.0000000010000000 -> NO
Ah, jadi K harus 1e16 atau lebih besar jika saya ingin 1e-13 menjadi 'nol'.
Jadi, saya katakan Anda memiliki dua opsi:
- Lakukan perhitungan epsilon sederhana menggunakan penilaian teknik Anda untuk nilai 'epsilon', seperti yang saya sarankan. Jika Anda melakukan grafik dan 'nol' dimaksudkan sebagai 'perubahan yang terlihat' daripada memeriksa aset visual Anda (gambar, dll) dan menilai epsilon apa yang bisa.
- Jangan mencoba perhitungan floating point sampai Anda membaca referensi jawaban non-kargo-kultus (dan dapatkan gelar Ph.D dalam prosesnya) dan kemudian gunakan penilaian non-intuitif untuk memilih
K
.
fabs(x+y)
bermasalah jikax
dany
(dapat) memiliki tanda yang berbeda. Namun, jawaban yang bagus terhadap gelombang perbandingan pemujaan kargo.