['Câu trả lời đúng' bóng bẩy khi chọn K
. Việc chọn K
kết thúc cũng giống như quảng cáo như chọn VISIBLE_SHIFT
nhưng việc chọn K
ít rõ ràng hơn vì không giống như VISIBLE_SHIFT
nó không có căn cứ trên bất kỳ thuộc tính hiển thị nào. Do đó chọn chất độc của bạn - chọn K
hoặc chọn VISIBLE_SHIFT
. Câu trả lời này ủng hộ việc lựa chọn VISIBLE_SHIFT
và sau đó thể hiện sự khó khăn trong việc lựa chọn K
]
Chính xác là do lỗi tròn, bạn không nên sử dụng so sánh các giá trị 'chính xác' cho các hoạt động logic. Trong trường hợp cụ thể của bạn về một vị trí trên màn hình hiển thị, có thể không có vấn đề gì nếu vị trí đó là 0,0 hoặc 0,0000000003 - sự khác biệt là vô hình trước mắt. Vì vậy, logic của bạn nên là một cái gì đó như:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
Tuy nhiên, cuối cùng, "vô hình trước mắt" sẽ phụ thuộc vào thuộc tính hiển thị của bạn. Nếu bạn có thể giới hạn trên màn hình (bạn sẽ có thể); sau đó chọn VISIBLE_SHIFT
là một phần của giới hạn trên.
Bây giờ, 'câu trả lời đúng' nằm trên K
vì vậy hãy khám phá chọn K
. "Câu trả lời đúng" ở trên cho biết:
K là hằng số bạn chọn sao cho sai số tích lũy của các tính toán của bạn chắc chắn bị ràng buộc bởi các đơn vị K ở vị trí cuối cùng (và nếu bạn không chắc chắn mình đã tính đúng ràng buộc tính toán, hãy làm cho K lớn hơn vài lần so với tính toán của bạn nói rằng nó nên được)
Vì vậy, chúng tôi cần K
. Nếu việc nhận K
được khó khăn hơn, ít trực quan hơn so với việc chọn của tôi VISIBLE_SHIFT
thì bạn sẽ quyết định những gì phù hợp với bạn. Để tìm thấy K
chúng tôi sẽ viết một chương trình thử nghiệm xem xét một loạt các K
giá trị để chúng tôi có thể thấy nó hoạt động như thế nào. Rõ ràng là nên chọn cách nào K
, nếu 'câu trả lời đúng' có thể sử dụng được. Không?
Chúng tôi sẽ sử dụng, như chi tiết 'câu trả lời đúng':
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Hãy thử tất cả các giá trị của 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
À, vậy K nên là 1e16 hoặc lớn hơn nếu tôi muốn 1e-13 là 'zero'.
Vì vậy, tôi muốn nói rằng bạn có hai lựa chọn:
- Thực hiện một tính toán epsilon đơn giản bằng cách sử dụng phán đoán kỹ thuật của bạn cho giá trị của 'epsilon', như tôi đã đề xuất. Nếu bạn đang làm đồ họa và 'zero' có nghĩa là 'thay đổi có thể nhìn thấy' hơn là kiểm tra tài sản hình ảnh của bạn (hình ảnh, v.v.) và đánh giá xem epsilon có thể là gì.
- Đừng thử bất kỳ tính toán dấu phẩy động nào cho đến khi bạn đọc tài liệu tham khảo câu trả lời không phải là hàng hóa (và nhận bằng tiến sĩ trong quá trình) và sau đó sử dụng phán đoán không trực quan của bạn để chọn
K
.
fabs(x+y)
là vấn đề nếux
vày
(có thể) có dấu hiệu khác nhau. Tuy nhiên, một câu trả lời tốt chống lại làn sóng so sánh tôn giáo hàng hóa.