Ưu điểm và nhược điểm của việc sử dụng cái này thay vì cái kia trong C ++ là gì?
Ưu điểm và nhược điểm của việc sử dụng cái này thay vì cái kia trong C ++ là gì?
Câu trả lời:
Nếu bạn muốn biết câu trả lời thực sự, bạn nên đọc Điều mà mọi nhà khoa học máy tính nên biết về số học dấu chấm động .
Tóm lại, mặc dù double
cho phép biểu diễn độ chính xác cao hơn , nhưng đối với một số phép tính nhất định, nó sẽ tạo ra sai số lớn hơn . Lựa chọn "đúng" là: sử dụng càng nhiều độ chính xác càng tốt nhưng không nhiều hơn và chọn đúng thuật toán .
Nhiều trình biên dịch thực hiện phép toán dấu phẩy động mở rộng ở chế độ "không nghiêm ngặt" (tức là sử dụng kiểu dấu phẩy động rộng hơn có sẵn trong phần cứng, ví dụ: 80-bit và 128-bit nổi), điều này cũng nên được tính đến. Trong thực tế, bạn khó có thể thấy bất kỳ sự khác biệt nào về tốc độ - dù sao thì chúng cũng là bản gốc của phần cứng.
double
- nó an toàn hơn trong hầu hết các trường hợp.
Trừ khi bạn có một số lý do cụ thể để làm khác, hãy sử dụng double.
Có lẽ đáng ngạc nhiên, nó là double chứ không phải float là kiểu dấu phẩy động "bình thường" trong C (và C ++). Các hàm toán học tiêu chuẩn như sin và log nhận gấp đôi đối số và trả về gấp đôi. Một ký tự dấu phẩy động bình thường, như khi bạn viết 3,14 trong chương trình của mình, có kiểu double. Không nổi.
Trên các máy tính hiện đại điển hình, tốc độ nhân đôi có thể nhanh như phao hoặc thậm chí nhanh hơn, vì vậy hiệu suất thường không phải là yếu tố cần xem xét, ngay cả đối với các phép tính lớn. (Và đó sẽ phải là những phép tính lớn , hoặc hiệu suất thậm chí không nằm trong tâm trí bạn. Máy tính để bàn i7 mới của tôi có thể thực hiện sáu tỷ phép nhân đôi trong một giây.)
Câu hỏi này là không thể trả lời vì không có ngữ cảnh cho câu hỏi. Dưới đây là một số điều có thể ảnh hưởng đến sự lựa chọn:
Trình biên dịch thực hiện phao, đôi và đôi dài. Tiêu chuẩn C ++ tuyên bố:
Có ba loại dấu chấm động: float, double, và long double. Loại double cung cấp độ chính xác ít nhất bằng float và loại long double cung cấp độ chính xác ít nhất là gấp đôi.
Vì vậy, cả ba có thể có cùng kích thước trong bộ nhớ.
Sự hiện diện của một FPU. Không phải tất cả các CPU đều có FPU và đôi khi kiểu dấu phẩy động được mô phỏng và đôi khi kiểu dấu chấm động không được hỗ trợ.
Kiến trúc FPU. FPU của IA32 là 80bit bên trong - các phao 32 bit và 64 bit được mở rộng thành 80bit khi tải và giảm khi lưu trữ. Ngoài ra còn có SIMD có thể thực hiện song song bốn phao 32bit hoặc hai phao 64bit. Việc sử dụng SIMD không được xác định trong tiêu chuẩn, vì vậy nó sẽ yêu cầu một trình biên dịch thực hiện phân tích phức tạp hơn để xác định xem SIMD có thể được sử dụng hay không, hoặc yêu cầu sử dụng các chức năng đặc biệt (thư viện hoặc bản chất). Kết quả của định dạng nội bộ 80bit là bạn có thể nhận được các kết quả hơi khác nhau tùy thuộc vào tần suất dữ liệu được lưu vào RAM (do đó, làm mất độ chính xác). Vì lý do này, các trình biên dịch không tối ưu hóa mã dấu chấm động đặc biệt tốt.
Băng thông bộ nhớ. Nếu một double yêu cầu nhiều bộ nhớ hơn float, thì sẽ mất nhiều thời gian hơn để đọc dữ liệu. Đó là câu trả lời ngây thơ. Trên IA32 hiện đại, tất cả phụ thuộc vào nguồn dữ liệu đến từ đâu. Nếu nó nằm trong bộ nhớ cache L1, tải không đáng kể với điều kiện dữ liệu đến từ một dòng bộ nhớ cache duy nhất. Nếu nó kéo dài nhiều hơn một dòng bộ nhớ cache thì sẽ có một chi phí nhỏ. Nếu là từ L2, thì phải mất một lúc lâu hơn, nếu ở trong RAM thì lâu hơn và cuối cùng, nếu ở trên đĩa thì đó là thời gian rất lớn. Vì vậy, sự lựa chọn float hoặc double ít quan trọng hơn cách dữ liệu được sử dụng. Nếu bạn muốn thực hiện một phép tính nhỏ trên nhiều dữ liệu tuần tự, thì nên chọn kiểu dữ liệu nhỏ. Thực hiện nhiều tính toán trên một tập dữ liệu nhỏ sẽ cho phép bạn sử dụng các kiểu dữ liệu lớn hơn với bất kỳ hiệu quả đáng kể nào. Nếu bạn' đang truy cập dữ liệu một cách rất ngẫu nhiên, khi đó việc lựa chọn kích thước dữ liệu là không quan trọng - dữ liệu được tải trong các trang / dòng bộ nhớ cache. Vì vậy, ngay cả khi bạn chỉ muốn một byte từ RAM, bạn có thể nhận được 32 byte được chuyển (điều này rất phụ thuộc vào kiến trúc của hệ thống). Trên hết, CPU / FPU có thể là siêu vô hướng (hay còn gọi là pipelined). Vì vậy, mặc dù tải có thể mất vài chu kỳ, CPU / FPU có thể bận làm việc khác (ví dụ: nhân) mà ẩn thời gian tải ở một mức độ.
Tiêu chuẩn không thực thi bất kỳ định dạng cụ thể nào cho các giá trị dấu chấm động.
Nếu bạn có một thông số kỹ thuật, thì điều đó sẽ hướng dẫn bạn đến sự lựa chọn tối ưu. Nếu không, bạn phải trải nghiệm xem nên sử dụng những gì.
Double chính xác hơn nhưng được mã hóa trên 8 byte. float chỉ có 4 byte, do đó ít chỗ hơn và kém chính xác hơn.
Bạn nên rất cẩn thận nếu bạn có double và float trong ứng dụng của mình. Tôi đã có một lỗi do đó trong quá khứ. Một phần của mã đang sử dụng float trong khi phần còn lại của mã đang sử dụng double. Sao chép double sang float và sau đó float thành double có thể gây ra lỗi độ chính xác có thể gây ảnh hưởng lớn. Trong trường hợp của tôi, đó là một nhà máy hóa chất ... hy vọng nó không gây ra hậu quả nghiêm trọng :)
Tôi nghĩ rằng chính vì loại lỗi này mà tên lửa Ariane 6 đã nổ cách đây vài năm !!!
Hãy suy nghĩ cẩn thận về loại được sử dụng cho một biến
Điều này phụ thuộc vào cách trình biên dịch thực hiện double. Nó hợp pháp khi double và float là cùng một loại (và nó có trên một số hệ thống).
Tuy nhiên, nếu chúng thực sự khác nhau, vấn đề chính là độ chính xác. Một đôi có độ chính xác cao hơn nhiều do sự khác biệt về kích thước. Nếu các số bạn đang sử dụng thường vượt quá giá trị của dấu phẩy, thì hãy sử dụng dấu kép.
Một số người khác đã đề cập đến vấn đề hiệu suất. Đó chính xác là thứ cuối cùng trong danh sách cân nhắc của tôi. Tính đúng đắn nên được bạn cân nhắc số 1.
Sử dụng bất kỳ độ chính xác nào được yêu cầu để đạt được kết quả thích hợp . Nếu sau đó bạn thấy rằng mã của mình không hoạt động tốt như bạn muốn (bạn đã sử dụng cấu hình đúng?), Hãy xem:
Tôi nghĩ bất kể sự khác biệt (như mọi người đã chỉ ra, float chiếm ít dung lượng hơn và nói chung là nhanh hơn) ... có ai từng gặp vấn đề về hiệu suất khi sử dụng double không? Tôi nói rằng hãy sử dụng double ... và nếu sau này bạn quyết định "wow, điều này thực sự chậm" ... hãy tìm điểm nghẽn hiệu suất của bạn (có thể không phải là thực tế bạn đã sử dụng double). VẬY, nếu nó vẫn còn quá chậm đối với bạn, hãy xem nơi bạn có thể hy sinh một số độ chính xác và sử dụng float.
Sự khác biệt chính giữa float và double là độ chính xác. Wikipedia có thêm thông tin về Độ chính xác đơn (float) và Độ chính xác kép .
Nó phụ thuộc nhiều vào CPU, sự cân bằng rõ ràng nhất là giữa độ chính xác và bộ nhớ. Với hàng GB RAM, bộ nhớ không phải là vấn đề lớn, vì vậy nói chung tốt hơn là sử dụng double
s.
Đối với hiệu suất, nó phụ thuộc nhiều vào CPU. float
s thường sẽ có hiệu suất tốt hơn double
s trên máy 32 bit. Trên 64 bit, double
s đôi khi nhanh hơn, vì nó (thường) là kích thước gốc. Tuy nhiên, điều quan trọng hơn việc bạn lựa chọn kiểu dữ liệu là liệu bạn có thể tận dụng các hướng dẫn SIMD trên bộ xử lý của mình hay không.
double có độ chính xác cao hơn, trong khi float chiếm ít bộ nhớ hơn và nhanh hơn. Nói chung, bạn nên sử dụng float trừ khi bạn gặp trường hợp nó không đủ chính xác.