Tại sao% f in các giá trị lớn khi các hằng số dấu phẩy động được truyền thay vì các biến?


9

Trong chương trình đã cho, tại sao tôi lại nhận được kết quả khác nhau cho mỗi printfs?

#include <stdio.h>
int main()
{
    float c = 4.4e10;
    printf("%f\n", c);
    printf("%f\n", 4.4e10);
    return 0;
}

Và nó hiển thị đầu ra sau:

44000002048.000000
44000000000.000000

4
Các câu trả lời cho đến nay giải thích rằng đó 4.4e10là một doublehằng số được chuyển đổi thành floattrong quá trình khởi tạo cnhưng được giữ nguyên doublekhi được chuyển đến printf. Tuy nhiên, bạn cũng có thể muốn biết rằng việc thêm một fhậu tố làm cho nó floatkhông đổi: In ấn 4.4e10fsẽ hiển thị cùng một giá trị mà kết quả từ việc khởi tạo cthành 4.4e10f. Phân biệt các floathằng số với các doublehằng số có thể rất quan trọng để thực hiện công việc chất lượng với số học dấu phẩy động.
Eric Postpischil

Là phương pháp chuyển đổi này được đặt tên bất cứ điều gì? Tôi muốn đọc về nó.
dùng10056563

Bạn có muốn biết khi nào việc chuyển đổi từ doubleđể floatxảy ra bằng ngôn ngữ C? Hoặc bạn có muốn biết những giá trị nào dẫn đến từ chuyển đổi, nghĩa là, những chuyển đổi có ảnh hưởng gì không? Hay cái gì khác?
Eric Postpischil

Tôi đang đặt câu hỏi không phải là câu trả lời ở đây cũng không phải là tiêu chuẩn, nhưng khi tôi còn trẻ và học Cchúng tôi đã sử dụng printf("%f",x)cho một floatprintf("%lf",x)cho một double. Khi nào mọi thứ thay đổi? Và làm thế nào một người rõ ràng printf a (đơn) float- printf("%hf",x)??
Adrian Mole

2
@Adrian %lftrong printf cũng giống như vậy %f. Một floatđối số trong biến được chuyển đổi thành một doublebởi trình biên dịch, giống như shortđược chuyển đổi thành một int.
SS Anne

Câu trả lời:


9

A floatlà loại chứa số dấu phẩy động 32 bit, trong khi hằng số 4.4e10đại diện cho a double, chứa số dấu phẩy động 64 bit (nghĩa là số dấu phẩy động kép )

Khi bạn gán 4.4e10cho c, giá trị 4.4e10không thể được biểu diễn chính xác (một lỗi làm tròn trong một tham số gọi là mantissa) và giá trị gần nhất có thể (44000002048) được lưu trữ. Khi nó được truyền đến printf, nó được thúc đẩy trở lại double, trong đó có lỗi làm tròn.

Trong trường hợp thứ hai, giá trị là doubletoàn bộ thời gian, không thu hẹp và mở rộng, và đó là trường hợp a doublecó thể biểu thị chính xác giá trị.

Nếu đây là hành vi không mong muốn, bạn có thể tuyên bố cdoublechính xác hơn một chút (nhưng hãy cẩn thận rằng cuối cùng bạn vẫn sẽ đạt giới hạn chính xác).


3

Bạn đang thực sự in các giá trị của hai loại khác nhau ở đây.

Trong trường hợp đầu tiên, bạn chỉ định một giá trị cho một biến loại float. Độ chính xác của a floatlà khoảng 6 hoặc 7 chữ số thập phân, vì vậy trừ khi giá trị có thể được biểu diễn chính xác, bạn sẽ thấy giá trị gần nhất có thể được biểu thị bằng loại đó.

Trong trường hợp thứ hai, bạn truyền hằng số 4.4e10có loại double. Loại này có khoảng 16 chữ số thập phân chính xác và giá trị nằm trong phạm vi đó, vì vậy giá trị chính xác được in.


Tại sao nó đặc biệt in 2048 ở cuối?
dùng10056563

@ user10056563 Bởi vì đó là số gần nhất với 4.4e10 có thể được lưu trữ trong một float 32 bit.
dbush
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.