Vào một ngày tôi đã tìm ra một lỗi
của một trong những ứng dụng Silverlight mà tôi đang so sánh các số dư
giữa chúng.
Trong chuyển động một hình ảnh của
tôi, tôi đã tăng ScaleTransform.ScaleX
lên "0.05" từ "0.0" đến "2.0 và kiểm tra thấy vấn đề ở
chỗ khi ScaleTransform.ScaleX=
"2.0" . Vấn đề là nó không bao giờ chính xác khi nó đạt 2.0.
Nói chuyện với các đồng nghiệp của tôi, có lẽ nó là hiệu ứng bên cạnh
việc phân chia số dư , việc chia cho 10 không đúng chính xác với
hai số dư . Thí dụ như, hãy nhìn vào debugger, khi tôi gán ScaleX =
1.05 giá trị thực tế của nó là 1.0499999523162842.
Moral of the story: "Comparing floating point is fraught with peril. Do not
rely on comparisons with floats or exact fuzzy with epsilon. That is, floating
computation has errors so never do equal comparisons. Also, you should
generally never introduce an epsilon and do a fuzzy comparison since it simply
pushes your bugs to some other range of numbers you likely don't test."
(Vì đoạn này khó mà dịch được xác
nghĩa nên kpopyo để nguyên văn, và ý nghĩa chính của đoạn này là một thủ thuật
khi lập trình. Tức là: Khi so sánh hai giá trị nào đó, ta không nên so sánh
không bằng, vì khi tính toán các giá trị có thể bị dư ra , mà nên so sánh bé
hơn hay lớn hơn . Giống như chủ đề của bài này " Nguy cơ của những giá
trị so sánh " )
Dưới đây là cách làm sai. Đây là một
vòng lặp vô định vì nó không bao giờ chính xác đến 2.0. Trong debugger của tôi
(chế độ debug có ghi các chi tiết tính toán) nó là 1.9999991655349731 và
sau đó là 2.0499992370605469.
scale.ScaleX = 0.0;
while (scale.ScaleX != 2.0)
{
scale.ScaleX += 0.05;
// Do stuff here...
}
Cách khác (so sánh bé hơn)
scale.ScaleX = 0.0;
while (scale.ScaleX < 2.0)
{
scale.ScaleX += 0.05;
// Do stuff here...
}
Thank you,
--Mike Snow