Cách so sánh các số một cách chính xác trong JavaScript – cách so sánh hai số trong javascript

Lời khuyên trong bài đăng này liên quan đến JavaScript, vì tất cả các số trong JavaScript là (hiện tại) IEEE-7 … Được gắn thẻ float, ieee, double, javascript.

Bạn đang xem : cách so sánh hai số trong javascript

Lời khuyên trong bài đăng này liên quan đến JavaScript, vì tất cả các số trong JavaScript là (hiện tại) IEEE-754 số dấu phẩy động chính xác kép. Tuy nhiên, mọi thứ ở đây đều có thể áp dụng như nhau cho bất kỳ ngôn ngữ nào có kiểu dấu phẩy động.

Tóm lại: Không sử dụng bài kiểm tra bình đẳng do ngôn ngữ cung cấp và không sử dụng hằng số “epsilon” do ngôn ngữ cung cấp làm “khả năng chịu lỗi” của bạn. Thay vào đó, hãy chọn sự khoan dung của riêng bạn.

Bây giờ, phiên bản dài (mà tôi đã viết ban đầu để đáp lại một số lời khuyên thiếu sót mà tôi tìm thấy trên mạng về cách so sánh các số trong JavaScript).



Vấn đề và một cách tiếp cận thiếu sót để giải quyết nó

Lấy mã (“xấu”) này để giải quyết vấn đề dấu phẩy động cổ điển của (0,1 + 0,2) == 0,3 trả về false:

  

let

f1

=

0,1

+

0,2

; < / p>

let

f2

=

0,3

;

bảng điều khiển

.

log

(

Toán

.

abs

(

f1

-

f2

)

& lt;

Số

.

EPSILON

);

// 'Đúng - Yippeee !!!'

Ok, rất tốt. Nhưng nó không thành công với các đầu vào khác:

  

let

f1

=

1000000,1

+

0,2

; < / p>

let

f2

=

1000000.3

;

bảng điều khiển

.

log

(

Toán

.

abs

(

f1

-

f2

)

& lt;

Số

.

EPSILON

);

// '!!!!!! sai !!!!!!! '

Mô hình cơ bản đang được sử dụng là hợp lý: tránh so sánh bình đẳng trực tiếp và kiểm tra xem hai số của bạn có nằm trong khoảng chênh lệch có thể chấp nhận được hay không. Tuy nhiên, dung sai được sử dụng đã bị chọn sai.



Tại sao Number.EPSILON không thực hiện được ví dụ thứ hai ở trên?

Thực sự rất nguy hiểm khi sử dụng Number.Epsilon làm “dung sai” để so sánh số.

Các ngôn ngữ khác có cấu trúc tương tự (các ngôn ngữ .Net đều có cấu trúc là double.Epsilon chẳng hạn). Nếu bạn kiểm tra bất kỳ tài liệu âm thanh nào cho các hằng số như vậy, chúng có xu hướng đi kèm với cảnh báo không sử dụng “epsilon dấu phẩy động” để so sánh.

“epsilon” được cung cấp bởi ngôn ngữ chỉ đơn giản là “số gia” nhỏ nhất có thể mà bạn có thể biểu thị với loại dấu phẩy động cụ thể đó. Đối với các số có độ chính xác kép IEEE, số đó (Number.EPSILON) là rất nhỏ!

Vấn đề với việc sử dụng nó để so sánh là các số dấu phẩy động được triển khai giống như ký hiệu khoa học, trong đó bạn có một số nhỏ (ish) các chữ số có nghĩa và một số mũ di chuyển dấu thập phân sang trái hoặc phải (có thể là một loooooooooooong cách trái hoặc phải).

Số dấu phẩy động có độ chính xác kép (như được sử dụng trong JavaScript) có khoảng 15 chữ số có nghĩa (thập phân). Điều đó có nghĩa là nếu bạn muốn giữ một số như 1.000.000.000 (10 chữ số có nghĩa), thì bạn chỉ có thể giữ một phân số lên đến khoảng năm hoặc sáu chữ số thập phân. Các số dấu phẩy động có độ chính xác kép 3.000.000.000.00001 và 3.000.000.000.000011 sẽ được coi là bằng nhau. (lưu ý rằng vì các số thực được lưu trữ dưới dạng nhị phân, nên không phải lúc nào cũng có chính xác 15 chữ số thập phân có nghĩa – thông tin bị mất ở một số lũy thừa của hai, không phải là lũy thừa của 10).

Number.EPSILON có kích thước nhỏ hơn .00001 – vì vậy, trong khi ví dụ đầu tiên hoạt động với “dung sai” là Number.EPSILON (vì các số đang được so sánh đều nhỏ hơn 1,0), ví dụ thứ hai bị hỏng.


Không có một kích thước phù hợp với tất cả “epsilon” để so sánh

Nếu bạn tìm kiếm trực tuyến, có một chút thảo luận về cách chọn một epsilon (hoặc dung sai) phù hợp để thực hiện so sánh. Sau tất cả các cuộc thảo luận và một số mã rất thông minh có khả năng tìm ra “epsilon phổ quát được tính toán động” (dựa trên số lớn nhất đang được so sánh), nó luôn kết thúc với điều này:

BẠN cần chọn dung sai phù hợp với ứng dụng của mình!

Lý do khiến dung sai được tính toán động (dựa trên quy mô của các con số được so sánh) không phải là một giải pháp phổ biến là khi một tập hợp các con số được so sánh có kích thước khác nhau, rất dễ dẫn đến tình huống phá vỡ một trong số quy tắc quan trọng nhất của bình đẳng: “bình đẳng phải có tính bắc cầu”. tức là

nếu a == b và b == c, thì a == c cũng phải đánh giá là TRUE!

Sử dụng một dung sai thay đổi với mọi thử nghiệm bình đẳng trong chương trình của bạn là một cách rất tốt để có a! = c ở đâu đó khi bạn mong đợi a và c bằng nhau một cách hợp lý. Bạn cũng có thể đảm bảo điều này sẽ xảy ra vào những thời điểm “ngẫu nhiên” khó chịu. Đó là con đường dẫn đến những người bạn ở Đảo Bug: hãy vào nếu bạn dám và cầu xin đấng toàn năng thương xót linh hồn bạn … arrrrrrrr ** !!!

** thực ra … “arrrghhhhhhhh !!!” thích hợp hơn



Chọn một dung sai cho ứng dụng của bạn

Vì vậy, làm cách nào để bạn chọn một dung sai phù hợp cho chương trình của bạn ? Tôi rất vui vì bạn đã hỏi! …

Giả sử bạn đang nắm giữ kích thước của một tòa nhà tính bằng milimét (trong đó một tòa nhà dài 20 mét sẽ là 20.000). Bạn có thực sự quan tâm đến kích thước đó có nằm trong khoảng 0,0000000001 milimet của một số kích thước khác khi so sánh không? – chắc là không!

Trong trường hợp này, epsilon hợp lý (hoặc dung sai) có thể là .01 hoặc .001 **. Cắm nó vào Math.abs (f1 - f2) & lt; thay vào đó là biểu thức dung sai .

Chắc chắn KHÔNG sử dụng Number.EPSILON cho ứng dụng này, vì bạn có thể nhận được một tòa nhà dài 200m ở đâu đó (200.000mm) và có thể không so sánh đúng với tòa nhà khác Kích thước dài 200m sử dụng Number.EPSILON của JavaScript.

** mọi thứ sẽ có xu hướng hoạt động tốt hơn nếu bạn sử dụng dung sai có thể được biểu diễn chính xác trong hệ nhị phân. Một số tùy chọn đơn giản tốt đẹp là quyền hạn của hai. ví dụ. 0,5 (2 ^ -1), 0,25 (2 ^ -2), 0,125 (2 ^ -3), 0,0625 (2 ^ -4), v.v.



Tránh các số dấu phẩy động bất cứ nơi nào bạn có thể

ngay cả trong JavaScript nơi chúng không thể tránh khỏi

Ngẫu nhiên, nếu bạn không quan tâm liệu các phép đo của mình trong ví dụ trước có gần nhau hơn 1mm hay không, thì có lẽ bạn chỉ nên sử dụng kiểu số nguyên và thực hiện với nó.

Nếu bạn đang làm việc trong JavaScript thì bạn [hiện tại **] bị mắc kẹt với các số dấu phẩy động. JavaScript thay thế thực sự duy nhất cung cấp là lưu trữ các số của bạn dưới dạng chuỗi. Đây thực sự có thể là một cách tiếp cận hợp lý đối với các số nguyên lớn chỉ cần được kiểm tra tính bình đẳng và không cần thực hiện các phép toán số trên chúng (chẳng hạn như khóa chính của cơ sở dữ liệu). Có một số “gotchas dấu phẩy động” khác đang chờ đợi khi bạn nhận được số nguyên đủ lớn để chứa nhiều hơn khoảng 15-16 chữ số! (cụ thể là bất kỳ thứ gì lớn hơn 9,007,199,254,740,991)

Tương tự như vậy (vẫn trong ví dụ về “mô hình tòa nhà” ở trên), nếu bạn chỉ quan tâm đến việc các phép đo của mình có cách nhau 0,1mm hay không, thì bạn có thể sử dụng loại “thập phân” (nếu ngôn ngữ của bạn hỗ trợ) hoặc chỉ lưu trữ nội bộ tất cả các phép đo của bạn dưới dạng số nguyên đại diện cho phần mười milimét (ví dụ: tòa nhà 20 mét = 200.000 “phần mười milimét” trong nội bộ)

Số dấu chấm động rất phù hợp với những gì chúng được thiết kế (tạo mô hình phức tạp về các phép đo hoặc tọa độ trong thế giới thực), nhưng chúng đưa sự kỳ lạ vào các phép tính liên quan đến tiền bạc hoặc những thứ khác mà chúng tôi mong đợi là “tốt đẹp và đồng đều”.

** Kể từ giữa năm 2019, đã có cuộc thảo luận về việc giới thiệu loại “BigInt” cho JavaScript (cung cấp một giải pháp thay thế cho số dấu phẩy động), nhưng nó chưa được hỗ trợ trong nhiều triển khai và nó không hoạt động đến một thông số kỹ thuật ECMAScript cuối cùng. Việc triển khai JavaScript V8 của Google dường như là một áp dụng sớm cùng với Mozilla, vì vậy, bạn có thể sử dụng nó trong các phiên bản hiện tại của Chrome, Firefox và các nền tảng dựa trên V8 khác ngay bây giờ.



Tại sao số dấu phẩy động lại kỳ lạ như vậy?

Nếu bạn vẫn chưa quen với 0,1 + 0,2! = 0,3 cũ, thì tôi đã tổng hợp một tài liệu bổ sung nhanh về cách hoạt động của số dấu phẩy động, điều này sẽ làm sáng tỏ sự điên rồ. < / p>

Tại sao Số Dấu phẩy động lại kỳ lạ & gt; & gt;



Đồ chơi tương tác: Hãy tiếp tục và phá vỡ mọi thứ

Nếu bạn muốn thử so sánh dấu phẩy động trong Javascript và tìm hiểu cách các con số mất độ chính xác khi chúng lớn hơn, thì có một jsfiddle mà tôi đã tổng hợp tại: https://jsfiddle.net/ r0begv7a / 3 /


Xem thêm những thông tin liên quan đến chủ đề cách so sánh hai số trong javascript

JavaScript Problem: Comparing Two Arrays without Loops

  • Tác giả: All Things JavaScript, LLC
  • Ngày đăng: 2020-11-11
  • Đánh giá: 4 ⭐ ( 7121 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: We are going to tackle another JavaScript problem in this tutorial. The specific problem is how one can compare two arrays without using any loops.

    Would you like to help keep this channel going?
    https://www.patreon.com/bePatron?u=7373521&redirect_uri=http%3A%2F%2Fallthingsjavascript.com%2Fcontribute.html&utm_medium=widget

    Earn SCRIPT: https://app.tryroll.com/claim/SCRIPT-FdhQGwpZXXnh

    Unlimited access to EVERY course for one low price: https://allthingsjavascript.teachable.com/p/javascript-the-complete-collection

    Access to EVERY course via subscription (get 2 months free): https://www.skillshare.com/r/profile/Steven-Hancock/24508

    Courses offered on Udemy at a discount (access from my site): http://allthingsjavascript.com/courses.html

    Tutorials referred to in this video:
    JavaScript Problem Playlist: https://www.youtube.com/playlist?list=PLTo9PCskHpbGawvd3GNAR7mfeFoM61v3y
    ES5 Methods Map and Reduce: https://youtu.be/RePO4I6PzSA

    Need Help? https://pensight.com/x/steven-hancock

    For more resources on JavaScript:
    http://www.allthingsjavascript.com

    javascript AllThingsJavaScriptLLC

Javascript căn bản – So sánh

  • Tác giả: techmaster.vn
  • Đánh giá: 5 ⭐ ( 4382 lượt đánh giá )
  • Khớp với kết quả tìm kiếm:

So sánh bằng trong Javascript

  • Tác giả: viblo.asia
  • Đánh giá: 3 ⭐ ( 2818 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Trong khi viết code, việc so sánh giữa các giá trị là điều phổ biến, thường đi liền với các lệnh điều kiện if else và như mọi người đều biết các ứng dụng thực tế sẽ phải xử lý rất nhiều case (if else…

Toán tử so sánh trong JavaScript

  • Tác giả: completejavascript.com
  • Đánh giá: 5 ⭐ ( 2371 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Bài viết trước, bạn đã biết toán tử là gì và các toán tử giúp tính toán. Bài viết này sẽ tìm hiểu toán tử so sánh trong JavaScript, kết quả phép so sánh và một số trường hợp đặc biệt.

Tại sao sử dụng === trong javascript để so sánh?

  • Tác giả: anonystick.com
  • Đánh giá: 5 ⭐ ( 7255 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Bài viết này chúng ta tập trung cho những bạn mới bắt đầu đi bước vào ngôn ngữ javascript. Đôi khi họ đã sử dụng Operator này để so sánh trong code nhưng sự thật đằng sau nó các developer javascipt vẫn còn chưa biết. Vì vậy chúng ta sẽ nói kỹ về vấn đề này và cùng thảo luận.

[Javascript Căn bản] Boolean và phép so sánh trong JavaScript

  • Tác giả: tuandc.com
  • Đánh giá: 5 ⭐ ( 2416 lượt đánh giá )
  • Khớp với kết quả tìm kiếm:

Biến so sánh trong JavaScript

  • Tác giả: hocjavascript.net
  • Đánh giá: 5 ⭐ ( 8122 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Có người vẫn nói vui rằng JavaScript là “The World’s Most Misunderstood Programming Language”, bởi có rất nhiều lập trình viên Web vẫn

Xem thêm các bài viết khác thuộc chuyên mục: Kiến thức lập trình

Xem Thêm  Hơn 70 CSS & HTML thực đơn Hamburger tốt nhất - menu thả xuống css hamburger