2012-12-08 30 views
10

Vì vậy, tôi đã tham gia cuộc thi điện toán và tôi đã nhận thấy một lỗi lạ. pow (26,2) sẽ luôn trả về 675, và đôi khi 674? Mặc dù câu trả lời chính xác là 676. Những loại lỗi này cũng xảy ra với pow (26,3), pow (26,4) vv Sau khi gỡ lỗi sau cuộc thi, tôi tin rằng câu trả lời phải làm với thực tế int rounds down. Điều thú vị là loại lỗi này chưa bao giờ xảy ra với tôi trước đây. Các máy tính tôi đã có được chạy mingw trên windows 8. Phiên bản GCC là khá mới, như 2-3 tháng tuổi tôi tin. Nhưng những gì tôi thấy là nếu tôi bật cờ tối ưu hóa o1/o2/o3 trên các loại lỗi này sẽ biến mất một cách thần kỳ. pow (26,2) sẽ luôn luôn nhận được 676 aka câu trả lời đúng Bất cứ ai có thể giải thích lý do tại sao?GCC C++ độ chính xác pow

#include <cmath> 
#include <iostream> 

using namespace std; 
int main() { 
    cout<<pow(26,2)<<endl; 
    cout<<int(pow(26,2))<<endl; 
} 

Kết quả có đôi là lạ.

double a=26; 
double b=2; 
cout<<int(pow(a,b))<<endl; #outputs 675 
cout<<int(pow(26.0,2.0))<<endl; # outputs 676 
cout<<int(pow(26*1.00,2*1.00))<<endl; # outputs 676 
+2

'pow (26,2)' như trong 26 * 26 = 676? –

+0

yea, pow như trong chức năng điện tiêu chuẩn. –

+0

Bạn có thể đăng mã của mình không? Tôi không chắc chắn làm thế nào bạn sẽ có được những giá trị này hoặc. –

Trả lời

10

Chức năng pow hoạt động trên hai giá trị dấu phẩy động và có thể nâng lên một giá trị khác. Điều này được thực hiện thông qua thuật toán gần đúng, vì nó được yêu cầu để có thể xử lý các giá trị từ nhỏ nhất đến lớn nhất.

Vì đây là một thuật toán gần đúng, đôi khi nó có giá trị sai một chút. Trong hầu hết các trường hợp, điều này là OK. Tuy nhiên, nếu bạn quan tâm đến việc có kết quả chính xác, đừng sử dụng nó.

Tôi đặc biệt khuyên bạn không nên sử dụng nó cho số nguyên. Và nếu toán hạng thứ hai được biết (2, trong trường hợp này) nó là tầm thường để thay thế điều này bằng mã thực hiện điều này nhanh hơn nhiều và trả về giá trị chính xác. Ví dụ:

int square(int x) 
{ 
    return x * x; 
} 

Để trả lời câu hỏi thực tế: Một số trình biên dịch có thể thay thế các cuộc gọi đến pow với các mã khác, hoặc loại bỏ nó tất cả cùng nhau, khi một hoặc cả hai lập luận được biết. Điều này giải thích lý do tại sao bạn nhận được kết quả khác nhau.

+1

Bất kỳ lý do cụ thể nào bạn đang đề xuất sử dụng macro và không phải là chức năng? – NPE

+1

Ngoài ra, tôi sẽ thay thế * được biết * với * là một số nguyên nhỏ đã biết *. Nó không được sử dụng nhiều nếu nó được biết đến là lớn hoặc phân số. – NPE

+0

@NPE, tôi đã chọn macro vì nó là loại trung tính và rất dễ gõ :). Tất nhiên, nếu bạn biết loại bạn có thể định nghĩa một hàm, cách khác là một tập hợp các hàm bị quá tải hoặc thậm chí là một hàm mẫu. – Lindydancer

Các vấn đề liên quan