Một số thực chia hết có được đảm bảo là 1.f không?


76

Nếu tôi viết:

int x = /* any non-zero integer value */;
float y = x;
float z = y / y;

zđược đảm bảo là chính xác 1.f không?


8
Nó sẽ đòi hỏi một số lượng tương đối bất thường, thậm chí theo tiêu chuẩn C ++, để lập luận rằng std::numeric_limits<int>::max()có thể lớn hơn std::numeric_limits<float>::max().
MSalters

2
@MSalters Haha, tôi đã nghĩ đến việc bao gồm điều đó, nhưng quyết định nó quá ngu ngốc. :)
Baum mit Augen

1
@MSalters: FWIW, đối với hầu hết x, static_cast<int>(y) != x(nếu cả hai đều là 32-bit), nhưng zvẫn sẽ bằng 1.0ftrừ khi x == 0cả mẫu số và mẫu số đều có cùng một lỗi làm tròn.
Arne Vogel

Nếu hai số xyđủ lớn, và đủ gần nhau (không bằng nhau), thì x/ycó thể sẽ 1.fquá, do lỗi chuyển đổi. Hãy thử gõ này trong giao diện điều khiển của trình duyệt của bạn (mà có lẽ còn sử dụng IEEE754) và nhấn ENTER: 9223372036854775700/9223372036854775800.
Cássio Renan

1
@ArneVogel: Thực ra, + INF / + INF là NaN, không 1.0
MSalters

Câu trả lời:


96

Nếu triển khai C ++ của bạn sử dụng IEEE754 thì có, điều này được đảm bảo. (Toán tử phép chia được yêu cầu để trả về giá trị dấu phẩy động tốt nhất có thể).

Các chỉ ngoại lệ cho y / y, nói chung, không phải là 1.flà những trường hợp khi yđược NaN, +Inf, -Inf, 0.f, và -0.f, hoặc nếu bạn đang ở trên một nền tảng nơi intrất rộng mà trường hợp nhất định nó không thể được đại diện trong một floatmà không có floatđược thiết lập để +Infhoặc -Inf1 . Bỏ qua điểm cuối cùng đó, trong trường hợp của bạn, điều đó có nghĩa là điều đó int x = 0;sẽ tạo ra ngoại lệ duy nhất.

IEEE754 rất phổ biến. Nhưng để kiểm tra chắc chắn, hãy kiểm tra giá trị của

std::numeric_limits<float>::is_iec559;

1 Ví dụ, một nền tảng với 128 bit intvà IEEE754 32 bit floatsẽ thể hiện hành vi này cho các giá trị nhất định của x.


2
Tôi không nghĩ ycó thể trở thành NaN.
Baum mit Augen

2
Nếu bạn muốn đi theo con đường này, bạn cũng sẽ cần thêm Inf, -Inf và -0f. :)
Baum mit Augen

2
@BaummitAugen: Có rất nhiều mẫu bit IEE754 NaN, một số mẫu có bộ bit dấu. Nhưng NaN != NaNđối với bất kỳ bitpattern nào của NaN, việc tranh luận xem "+ NaN == -NaN" là vô nghĩa.
MSalters

1
Giả sử ygiá trị đó vừa nằm trong một thanh ghi vừa trong bộ nhớ, và trình biên dịch đã chọn tải mẫu số từ bộ nhớ. Vì vậy, bạn kết thúc với y_from_register / y_from_memory. Nếu thanh ghi có độ chính xác cao hơn bộ nhớ, điều gì đảm bảo rằng 1 là kết quả chia tốt nhất?
David Schwartz

1
Một ngoại lệ khác là khi floatkhông thể chứa xgiá trị của.
Nat

33

Không, không phải trong mọi trường hợp, ngay cả đối với IEEE754.

Ví dụ: với int x = 0;, bạn sẽ nhận được NaN. ( Trực tiếp )


Chỉ cần đưa câu trả lời đó vào câu trả lời của tôi trước khi bạn đăng cái này. Có một ủng hộ.
Bathsheba,

Tôi thấy từ ngữ của bạn không rõ ràng và gây hiểu lầm nên tôi đã đề xuất một chỉnh sửa để làm cho nó rõ ràng hơn.
cat

3
@cat Tôi có thể hiểu phần "không phải trong mọi trường hợp" trong đề xuất của bạn, nhưng việc bạn sử dụng "Ví dụ" cho thấy rằng có những giá trị khác cũng áp dụng tương tự và do đó, cá nhân tôi nghĩ câu trả lời ở đây bây giờ tốt hơn câu trả lời bạn đề xuất.

@hvd khi y là infhay 0fhoặc dấu hiệu biến thể của những người thì kết quả cũng không phải là1f
mèo

3
@cat Câu hỏi đặc biệt là về một số nguyên chia cho chính nó và có float y = x;với int x;.
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.