Sự khác biệt lớn.
Như tên của nó, a doublecó độ chính xác gấp 2 lần [1] . Nói chung a có 15 chữ số thập phân chính xác, trong khi có 7.floatdoublefloat
Đây là cách tính số chữ số:
doublecó 52 bit mantissa + 1 bit ẩn: log (2 53 ) log (10) = 15,95 chữ số
floatcó 23 bit mantissa + 1 bit ẩn: log (2 24 ) log (10) = 7,22 chữ số
Mất chính xác này có thể dẫn đến các lỗi cắt ngắn lớn hơn được tích lũy khi thực hiện các phép tính lặp lại, ví dụ
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
trong khi
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Ngoài ra, giá trị tối đa của float là về 3e38, nhưng gấp đôi là về 1.7e308, vì vậy việc sử dụng floatcó thể đạt "vô cực" (tức là một số dấu phẩy động đặc biệt) dễ dàng hơn nhiều so doublevới một cái gì đó đơn giản, ví dụ như tính toán giai thừa 60.
Trong quá trình thử nghiệm, có thể một vài trường hợp thử nghiệm chứa những con số khổng lồ này, điều này có thể khiến các chương trình của bạn bị lỗi nếu bạn sử dụng phao.
Tất nhiên, đôi khi, thậm chí doublekhông đủ chính xác, do đó đôi khi chúng ta có long double[1] (ví dụ trên cho 9.000000000000000066 trên Mac), nhưng tất cả các loại dấu phẩy động đều bị lỗi làm tròn , vì vậy nếu độ chính xác là rất quan trọng (ví dụ: tiền xử lý) bạn nên sử dụng inthoặc một lớp phân số.
Hơn nữa, không sử dụng +=để tổng hợp nhiều số dấu phẩy động, vì các lỗi tích lũy nhanh chóng. Nếu bạn đang sử dụng Python, hãy sử dụng fsum. Nếu không, hãy thử thực hiện thuật toán tổng hợp Kahan .
[1]: Tiêu chuẩn C và C ++ không chỉ định các đại diện của float, doublevà long double. Có thể là cả ba đều được triển khai dưới dạng chính xác kép của IEEE. Tuy nhiên, đối với hầu hết kiến trúc (gcc, MSVC; x86, x64, ARM) float là thực sự là một IEEE đơn chính xác số điểm (binary32) nổi, và double là một đôi có độ chính xác nổi số điểm IEEE (binary64).