Bạn dường như chú ý đến những lợi ích của việc sử dụng loại dấu phẩy động. Tôi có xu hướng thiết kế các số thập phân trong mọi trường hợp và dựa vào một trình lược tả để cho tôi biết nếu các thao tác trên thập phân có gây ra tắc nghẽn hoặc chậm lại. Trong những trường hợp đó, tôi sẽ "giảm" xuống gấp đôi hoặc thả nổi, nhưng chỉ thực hiện bên trong và cố gắng cẩn thận để quản lý mất độ chính xác bằng cách giới hạn số chữ số có nghĩa trong hoạt động toán học đang được thực hiện.
Nói chung, nếu giá trị của bạn là nhất thời (không được sử dụng lại), bạn an toàn khi sử dụng loại dấu phẩy động. Vấn đề thực sự với các loại dấu phẩy động là ba kịch bản sau đây.
- Bạn đang tổng hợp các giá trị dấu phẩy động (trong trường hợp đó là hợp chất lỗi chính xác)
- Bạn xây dựng các giá trị dựa trên giá trị dấu phẩy động (ví dụ: trong thuật toán đệ quy)
- Bạn đang làm toán với rất nhiều chữ số có nghĩa (ví dụ
123456789.1 * .000000000000000987654321
:)
BIÊN TẬP
Theo tài liệu tham khảo về số thập phân C # :
Các chữ số thập phân từ khóa biểu thị một kiểu dữ liệu 128-bit. So với các loại dấu phẩy động, loại thập phân có độ chính xác cao hơn và phạm vi nhỏ hơn, điều này làm cho nó phù hợp cho các tính toán tài chính và tiền tệ.
Vì vậy, để làm rõ tuyên bố trên của tôi:
Tôi có xu hướng thiết kế các số thập phân trong mọi trường hợp và dựa vào một trình lược tả để cho tôi biết nếu các thao tác trên thập phân có gây ra tắc nghẽn hoặc chậm lại.
Tôi chỉ từng làm việc trong các ngành công nghiệp nơi số thập phân thuận lợi. Nếu bạn đang làm việc trên các công cụ đồ họa hoặc đồ họa, có lẽ sẽ có ích hơn nhiều khi thiết kế cho loại dấu phẩy động (float hoặc double).
Số thập phân không chính xác vô hạn (không thể biểu thị độ chính xác vô hạn cho tính không tách rời trong một kiểu dữ liệu nguyên thủy), nhưng nó chính xác hơn nhiều so với gấp đôi:
- số thập phân = 28-29 chữ số có nghĩa
- gấp đôi = 15-16 chữ số có nghĩa
- float = 7 chữ số có nghĩa
CHỈNH SỬA 2
Đáp lại bình luận của Konrad Rudolph , mục số 1 (ở trên) hoàn toàn chính xác. Tập hợp của sự thiếu chính xác thực sự hợp chất. Xem mã dưới đây để biết ví dụ:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
Điều này xuất ra như sau:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
Như bạn có thể thấy, mặc dù chúng tôi đã thêm từ cùng một nguồn, nhưng kết quả của nhân đôi ít chính xác hơn (mặc dù có thể sẽ làm tròn chính xác) và độ nổi ít chính xác hơn, đến mức nó đã được giảm xuống chỉ còn hai chữ số có nghĩa.