2015-03-05 18 views
5

Tôi hiện đang viết một chương trình cần lấy sàn của căn bậc hai. Vì giá trị tôi lấy căn bậc hai là tích cực, tôi chỉ chuyển nó thành int. Vì vậy, nói cho ví dụ sau:C++ - Cách truyền chính xác gấp đôi thành int

int i = 16; 
int j = std::sqrt(i) 

j nên 4.

tôi tự hỏi, mặc dù nó có thể là sqrt trả 3,9999999991 thay vì 4,000000001 hoặc bất cứ điều gì, và kết quả của j là 3? Có quy tắc xác định hành vi điểm nổi? Làm thế nào tôi có thể chuyển đổi đúng cách này thành một int?

+9

int integer = std :: round (floating_point); –

+0

Hơi liên quan nếu bạn quan tâm đến làm tròn: https://stackoverflow.com/questions/485525/round-for-float-in-c – tux3

+0

@ DieterLücking Tôi nghĩ rằng sẽ tròn thành * gần nhất *, trong khi kết quả mong muốn ở đây là vòng xuống từ những gì sẽ là căn bậc hai "đúng". Ví dụ. sqrt (16) -> 4, sqrt (15) -> 3 –

Trả lời

3

Hầu như tất cả phần cứng có sẵn rộng rãi đều sử dụng số điểm nổi IETF754, mặc dù C++ không yêu cầu nó.

Giả sử số dấu chấm động IETF754 và một ánh xạ trực tiếp của ::std::sqrt đến IETF754 nổi điểm hoạt động căn bậc hai, bạn được đảm bảo những điều sau đây:

  • 16 và 4 đều có thể được biểu diễn chính xác trong nổi điểm số học - trên thực tế, độ chính xác gấp đôi số dấu chấm động có thể đại diện cho bất kỳ số nguyên 32 bit chính xác
  • căn bậc hai trả về kết quả đó là gần nhất để trở thành chính xác

Vì vậy, ví dụ bạn will work fine.

Nói chung, vấn đề bạn đã gợi ý có thể xảy ra, nhưng để giải quyết nó bạn phải đặt một câu hỏi lớn hơn: Trong trường hợp nào là một số gần với tích phân, thực sự không thể thiếu?

Điều này thực sự khó hơn nó có vẻ, vì bạn muốn tính toán sàn của căn bậc hai, và do đó chỉ đơn giản làm tròn sẽ không hoạt động cho bạn. Tuy nhiên, một khi bạn đã trả lời câu hỏi này cho chính mình, việc thực hiện một giải pháp khá đơn giản. Ví dụ:

int i = 16; 
int j = std::sqrt(i); 
if((j + 1) * (j + 1) == i) j += 1; 
Các vấn đề liên quan