Nếu ai đó vẫn tiếp cận trang này với các vấn đề tương tự khi phép trừ số nổi gây ra lỗi hoặc các giá trị lạ. Tôi muốn giải thích vấn đề này với chi tiết hơn một chút. Thủ phạm là số dấu phẩy động. Và các hệ điều hành khác nhau và các phiên bản khác nhau của ngôn ngữ lập trình có thể hoạt động khác nhau.
Để minh họa sự cố, tôi sẽ giải thích lý do tại sao bằng ví dụ đơn giản bên dưới.
Nó không liên quan trực tiếp đến PHP và nó không phải là lỗi. Tuy nhiên, mọi lập trình viên đều phải nhận thức được vấn đề này.
Vấn đề này thậm chí đã mất nhiều mạng sống hai thập kỷ trước. Vào ngày 25 tháng 2 năm 1991, vấn đề này trong tính toán số trôi nổi trong một pin tên lửa Patriot MIM-104 ngăn chặn nó chặn một tên lửa Scud đến ở Dhahran, Saudi Arabia, góp phần vào cái chết của 28 binh sĩ từ Quân Đoàn 14 của Quân Đoàn Hoa Kỳ.
Nhưng tại sao lại xảy ra?
Lý do là các giá trị dấu phẩy động biểu thị độ chính xác giới hạn. Vì vậy, một giá trị có thể không có cùng một chuỗi đại diện sau khi xử lý bất kỳ. Nó cũng bao gồm viết một giá trị dấu chấm động trong tập lệnh của bạn và trực tiếp in nó mà không có bất kỳ phép toán nào.
Chỉ cần một ví dụ đơn giản:
$a = '36';
$b = '-35.99';
echo ($a + $b);
Bạn mong chờ nó để in 0.01, phải không? Nhưng nó sẽ in một câu trả lời rất lạ như 0.009999999999998
Giống như các số khác, số dấu phẩy động kép hoặc nổi được lưu trữ trong bộ nhớ dưới dạng chuỗi 0 và 1.Cách dấu phẩy động khác với số nguyên là cách chúng ta diễn giải số 0 và 1 khi chúng ta muốn xem chúng. Có nhiều tiêu chuẩn cách chúng được lưu trữ.
số Floating-point thường được đóng gói vào một dữ kiện máy tính như là bit dấu, lĩnh vực mũ và significand hoặc mantissa, từ trái sang phải ....
số thập phân không tốt trong hệ nhị phân do thiếu đủ không gian. Vì vậy, uou không thể thể hiện 1/3 chính xác như nó là 0.3333333 ..., phải không? Tại sao chúng ta không thể biểu diễn 0,01 như một số phao nhị phân là vì lý do tương tự. 1/100 là 0.00000010100011110101110000 ..... với số 10100011110101110000 lặp lại.
Nếu 0,01 được giữ ở dạng đơn giản và được cắt ngắn theo hệ thống là 01000111101011100001010 khi được dịch ngược lại, nó sẽ được đọc như 0.0099999. ... tùy thuộc vào hệ thống (64bit máy tính sẽ cho bạn độ chính xác tốt hơn nhiều so với 32 bit). Hệ điều hành quyết định trong trường hợp này cho dù in nó như nó thấy hay làm thế nào để làm cho nó theo cách dễ đọc hơn. Vì vậy, nó phụ thuộc vào máy như thế nào họ muốn đại diện cho nó. Nhưng nó có thể được bảo vệ ở cấp độ ngôn ngữ với các phương pháp khác nhau.
Nếu bạn định dạng kết quả, hãy echo number_format (0.009999999999998, 2); nó sẽ in 0,01.
Đó là vì trong trường hợp này, bạn hướng dẫn cách đọc và độ chính xác mà bạn yêu cầu.
Điều tra 'độ chính xác' trong php.ini để có nhiều thay đổi hơn, thay đổi trên toàn PHP. Tuy nhiên, lưu ý rằng bạn đang xử lý * các chữ số có nghĩa * ở đó. –