Khi so sánh phao, bạn gọi ngưỡng của sự khác biệt là gì?


10

Tôi đang so sánh các float trong Java ngay bây giờ và công thức đơn giản nhất là:

Math.abs(a - b) < THRESHOLD

Khi đặt tên biến của bạn cho ngưỡng của sự khác biệt, bạn nên đặt tên nó là delta hay epsilon ? Cụ thể, điều nào trong hai là thuật ngữ chính xác cho giá trị nhỏ nhất mà số dấu phẩy động có thể biểu thị?

Là thuật ngữ ngôn ngữ lập trình cụ thể, hay nó là phổ quát trên các ngôn ngữ?


1
Thuật ngữ thay thế: "chính xác", "độ phân giải". Tôi thích những thứ này một cách chính xác;) bởi vì chúng không có vẻ quá kỹ thuật.
stakx

1
Off-topic: Các Floating-Point Hướng dẫn khuyến cáo chống lại sử dụng loại so sánh này gần như bình đẳng.
stakx

1
@stakx - các thuật ngữ bạn đề xuất không chính xác và có ý nghĩa khác với những gì OP đang hỏi về. Câu hỏi là chi tiết, có, nhưng nó có thể trả lời được dựa trên tham chiếu bên ngoài và nó có liên quan đến lập trình khi xử lý các giá trị dấu phẩy động. Đó là xây dựng và về chủ đề.

1
@ GlenH7: Tôi chưa bao giờ nói rằng câu hỏi không phải là một câu hỏi hay, hoặc không thể trả lời được. Trong thực tế, tôi là người đã nâng đỡ nó. Và vì bạn cho rằng các thuật ngữ (ít chính xác hơn) mà tôi đề xuất là không chính xác, tôi rất muốn tìm hiểu lý do tại sao lại như vậy.
stakx

@stakx - xin lỗi vì ngụ ý bạn đã bỏ phiếu để đóng. Tôi đã phản ứng nhiều hơn với bốn phiếu gần với câu hỏi tại thời điểm này.

Câu trả lời:


18

Epsilon trong toán học và kỹ thuật

Trong toán học và kỹ thuật nói chung:

  • Delta thường được sử dụng để chỉ một sự khác biệt, có thể ở bất kỳ quy mô nào.
  • Epsilon thường được sử dụng để chỉ một số lượng không đáng kể.

và epsilon có vẻ thích hợp hơn trong trường hợp của bạn.


Epsilon trong khoa học máy tính

Trong khoa học máy tính nói riêng, thuật ngữ epsilon cũng dùng để chỉ máy đặc biệt đo lường sự khác biệt giữa 1.0fvà phao nhỏ nhất lớn hơn hẳn 1.0f. Số sau này 1.00000011920928955078125fdành cho số float trong Java và có thể được tính bằng:

float f = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1);

Định nghĩa của epsilon máy phù hợp với việc sử dụng chung của epsilon được mô tả ở trên.


So sánh phao

Tuy nhiên, lưu ý rằng trước khi so sánh phao cho "độ gần", bạn cần có ý tưởng về quy mô của chúng. Hai phao rất lớn và được cho là rất khác nhau có thể bằng nhau:

9223372036854775808f == 9223372036854775808f + 1000000000f; //this is true!

Và ngược lại, có thể có nhiều giá trị float có thể (và một số bậc độ lớn) giữa hai phao nhỏ khác nhau bởi epsilon "chỉ". Trong ví dụ bên dưới, có 10.000.000 giá trị float có sẵn giữa smallf, nhưng sự khác biệt của chúng vẫn thấp hơn nhiều so với epsilon của máy:

float small = Float.MIN_VALUE; // small = 1.4E-45
float f = Float.intBitsToFloat(Float.floatToIntBits(small) + 100000000); // f = 2.3122343E-35
boolean b = (f - small < 0.00000011920928955078125f); //true!

Bài báo được liên kết trong câu trả lời của GlenH7 điều tra so sánh nổi hơn nữa và đề xuất một số giải pháp để khắc phục những vấn đề này.


2
-1: Trong phần mềm tính toán khoa học, Epsilon đề cập đến máy epsilon hoặc epsilon tương đối (xem cùng bài viết). Thông thường, đây không phải là cùng một số lượng được sử dụng trong việc chấp nhận sự bằng nhau gần đúng, bởi vì các lỗi làm tròn là bội số của epsilon máy hoặc epsilon tương đối, và thường là một số bậc lớn hơn thế.
rwong

1
@rwong Đó là một chuyên ngành của thuật ngữ epsilon , và có nhiều thứ khác. Trong kỹ thuật nói chung, epsilon đề cập đến một số lượng nhỏ hoặc một lỗi và Máy epsilon tương thích với ý tưởng đó.
assylias

@assylias, sử dụng tên có định nghĩa chuẩn, trong ngữ cảnh mà định nghĩa chuẩn có ý nghĩa, nhưng đối với một cái gì đó không tương ứng với định nghĩa tiêu chuẩn là một biên nhận cho các vấn đề.
AProgrammer

@AProgrammer Tôi không đồng ý rằng định nghĩa chung về epsilon không áp dụng được cho máy tính.
assylias

1
@assylias: cảm ơn đã làm rõ. Tôi đã xóa -1.
rwong

16

Trong toán học, delta được sử dụng để biểu thị một số khác biệt từ một giá trị, epsilon được sử dụng để biểu thị một giá trị lỗi tùy ý. Trong trường hợp này, epsilon sẽ là tên thông thường.


8

Để trực tiếp trả lời câu hỏi của bạn, bạn muốn sử dụng thuật ngữ này epsilon. Chính xác hơn, đó là machine epsiloncách sử dụng phổ biến làm giảm "máy" và chỉ sử dụng epsilon.

Nhìn vào bản sao địa phương của float.htôi, tôi thấy:

#define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */  
#define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */  
#define LDBL_EPSILON    DBL_EPSILON             /* smallest such that 1.0+LDBL_EPSILON != 1.0 */

Và các ý kiến ​​liên quan cho thấy rõ ràng rằng epsilon là thuật ngữ bạn đang đề cập đến.

Nhưng chúng ta cũng có thể dựa vào một số tài liệu tham khảo bên ngoài khác để xác minh đó epsilonlà thuật ngữ chính xác. Xem ở đây , ở đây , ở đây và cuối cùng là sự kết hợp của các thẻ truy vấn SO . Tôi không thể tìm thấy một tài liệu tham khảo trực tiếp đến tiêu chuẩn IEEE 754 để trích dẫn.


Bạn đã không hỏi, nhưng tôi thấy tài liệu tham khảo này rất phù hợp với ví dụ bạn cung cấp để làm rõ câu hỏi của bạn.

Hãy xem bài viết trên blog này của Bruce Dawson của Valve về việc so sánh các giá trị dấu phẩy động để hiểu rõ hơn về lý do tại sao bạn không muốn sử dụng phép so sánh mà bạn đề xuất.

Có khá nhiều thông tin được đóng gói trong bài viết đó, nhưng đây là snipppet có liên quan nhất từ ​​đó:

Nếu so sánh float cho bình đẳng là một ý tưởng tồi thì làm thế nào để kiểm tra xem sự khác biệt của chúng có nằm trong giới hạn lỗi hoặc giá trị epsilon hay không, như sau:

bool isEqual = fabs(f1 – f2) <= epsilon;

Với tính toán này, chúng ta có thể diễn tả khái niệm hai chiếc phao đủ gần để chúng ta muốn coi chúng là bằng nhau. Nhưng giá trị nào chúng ta nên sử dụng cho epsilon?
Với thử nghiệm của chúng tôi ở trên, chúng tôi có thể bị cám dỗ sử dụng lỗi trong tổng của chúng tôi, đó là khoảng 1,19e-7f. Trên thực tế, thậm chí còn có một định nghĩa trong float.h với giá trị chính xác đó và được gọi là FLT_EPSILON.
Rõ ràng đó là nó. Các vị thần tập tin tiêu đề đã nói và FLT_EPSILON là một epsilon thực sự!
Ngoại trừ đó là rác. Đối với các số từ 1.0 đến 2.0 FLT_EPSILON thể hiện sự khác biệt giữa các số float liền kề. Đối với các số nhỏ hơn 1.0, một epsilon của FLT_EPSILON nhanh chóng trở nên quá lớn và với các số đủ nhỏ, FLT_EPSILON có thể lớn hơn các số bạn đang so sánh!

Dawson xem xét khá nhiều cân nhắc khác về những rắc rối liên quan khi so sánh phao và xử lý các giá trị rất nhỏ như thế này, vì vậy tôi sẽ khuyến khích bạn đọc phần còn lại của bài viết của mình.


Bạn có thể muốn làm rõ phần đầu tiên trong câu trả lời của mình: Bài viết của Bruce đã giải thích lý do tại sao người ta không nên sử dụng một epsilon không đổi (chẳng hạn như phần được xác định trong tệp tiêu đề) để so sánh dung sai. Ngoài ra, trong nhiều trường hợp, lỗi của một vài triệu ULP không phải là điều đáng lo ngại, bởi vì trong hầu hết các ứng dụng, chúng tôi quan tâm nhiều hơn đến các chữ số có ý nghĩa nhiều hơn các lỗi trong các chữ số có ý nghĩa nhỏ nhất, bởi vì độ chính xác kép đã mang lại nhiều chữ số hơn chúng ta quan tâm.
rwong

@rwong - Khi tôi đọc nó, câu hỏi là xác định thuật ngữ chính xác để sử dụng cho tên hằng. Vì vậy, đó là lý do tại sao tôi cung cấp tài liệu tham khảo float.h cùng với một vài người khác cho máy epsilon. Bài viết từ Dawson là một cái gì đó tôi tìm thấy trong khi tìm kiếm tài liệu tham khảo IEEE 754 và tôi nghĩ có liên quan đến OP simplest formulađể so sánh. Nhiều người sử dụng cách tiếp cận đó như một nỗ lực đầu tiên, và tôi đã bao gồm bài viết của Dawson bởi vì nó thực sự đi sâu vào các sắc thái của việc so sánh khó khăn như thế nào. Vì vậy, tôi đã cố gắng trả lời trực tiếp câu hỏi và sau đó chỉ ra lý do tại sao không sử dụng nó theo cách đó.

5

Đây là một chức năng lỗi; sai số tuyệt đối thường được gọi là ε (epsilon) hoặc Δ x đối với một số lượng x:

ε = | dự kiến - thực tế |

Δ x = | x 0 - x  |

Lỗi tương đối đôi khi được gọi là η (eta):

η = | 1 - thực tế / dự kiến |

Đối với mục đích lập trình, absoluteErrorrelativeError(hoặc một số chữ viết tắt của chúng) là mô tả nhiều hơn. Nếu bạn muốn khẳng định rằng sai số nhỏ hơn một giá trị nhất định, giá trị đó đơn giản sẽ được gọi là ngưỡng hoặc dung sai .

Xem:


3

Tôi sẽ gọi nó là "khoan dung".

Có thể đó không phải là thuật ngữ chính xác về mặt toán học, nhưng thực tế mà bạn đặt câu hỏi ngụ ý với tôi rằng "delta" hay "epsilon" sẽ không phải là một tên biến tốt để sử dụng.

Theo kinh nghiệm của tôi, tốt hơn là sử dụng tên định danh có ý nghĩa với những người thực sự sẽ đọc mã. Cái tên nào hoàn toàn chính xác nếu nó có nghĩa là người đọc cần tra cứu nó trên Wikipedia để hiểu ý nghĩa của nó?


+1. Tôi luôn hy vọng mọi người hỏi đồng nghiệp của họ về những câu hỏi đặt tên này cũng như đăng ở đây.
MarkJ

6
-1, Tốt hơn để học các quy ước hơn là tránh chúng.
djechlin

+1 vì đây là lý do chính xác giống như tôi đã đăng câu hỏi này.
NobleUplift
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.