Nếu tôi viết:
int x = /* any non-zero integer value */;
float y = x;
float z = y / y;
Có z
được đảm bảo là chính xác 1.f không?
Nếu tôi viết:
int x = /* any non-zero integer value */;
float y = x;
float z = y / y;
Có z
được đảm bảo là chính xác 1.f không?
x
, static_cast<int>(y) != x
(nếu cả hai đều là 32-bit), nhưng z
vẫn sẽ bằng 1.0f
trừ khi x == 0
cả mẫu số và mẫu số đều có cùng một lỗi làm tròn.
x
và y
đủ lớn, và đủ gần nhau (không bằng nhau), thì x/y
có thể sẽ 1.f
quá, 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âu trả lời:
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.f
là 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 int
rất rộng mà trường hợp nhất định nó không thể được đại diện trong một float
mà không có float
được thiết lập để +Inf
hoặc -Inf
1 . 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 int
và IEEE754 32 bit float
sẽ thể hiện hành vi này cho các giá trị nhất định của x
.
y
có thể trở thành NaN.
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.
y
giá 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?
float
không thể chứa x
giá trị của.
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 )
inf
hay 0f
hoặ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
std::numeric_limits<int>::max()
có thể lớn hơnstd::numeric_limits<float>::max()
.