2008-10-30 26 views
25

Tôi đã nghe nói về "lỗi" khi sử dụng các biến số dấu phẩy động. Bây giờ tôi đang cố gắng để giải quyết câu đố này và tôi nghĩ rằng tôi nhận được một số lỗi làm tròn/dấu chấm động. Vì vậy, tôi cuối cùng sẽ tìm ra những điều cơ bản của lỗi dấu chấm động.Ví dụ đơn giản về lỗi dấu chấm động/làm tròn là gì?

Ví dụ đơn giản về lỗi điểm/làm tròn nổi (tốt nhất là trong C++) là gì?

Chỉnh sửa: Ví dụ: nói rằng tôi có sự kiện có p xác suất thành công. Tôi làm sự kiện này 10 lần (p không thay đổi và tất cả các thử nghiệm đều độc lập). Xác suất chính xác của 2 thử nghiệm thành công là gì? Tôi có mã này là:

double p_2x_success = pow(1-p, (double)8) * pow(p, (double)2) * (double)choose(8, 2); 

Đây có phải là cơ hội cho lỗi dấu chấm động không?

+0

Tôi nghĩ rằng những gì bạn thực sự cần điều này là: [gì Mỗi nhà khoa học máy tính nên biết về Floating-Point Arithmetic] (http://docs.sun.com/source/ 806-3568/ncg_goldberg.html). – Patrick

+0

Đọc bài này: http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1 –

+0

Xem ví dụ Java đơn giản, shuld giống nhau trong C: http://stackoverflow.com/ a) 15790782/254109 – xmedeko

Trả lời

9

Nói chung, lỗi dấu phẩy động đề cập đến khi một số không thể lưu trữ trong biểu diễn điểm nổi IEEE.

Số nguyên được lưu trữ với bit nhiều nhất là 1 và mỗi bit ở bên trái gấp đôi (2,4,8, ...). Thật dễ dàng để thấy rằng điều này có thể lưu trữ bất kỳ số nguyên lên đến 2^n, trong đó n là số bit.

Phần xác định (phần thập phân) của số dấu phẩy động được lưu trữ theo cách tương tự, nhưng di chuyển sang trái sang phải và mỗi bit liên tiếp bằng một nửa giá trị của số trước đó. (Nó thực sự phức tạp hơn một chút so với điều này, nhưng nó sẽ làm ngay bây giờ). Vì vậy, các con số như 0.5 (1/2) dễ dàng lưu trữ, nhưng không phải mọi số < 1 có thể được tạo bằng cách thêm một số lượng cố định các phần của dạng 1/2, 1/4, 1/8, ...

Ví dụ thực sự đơn giản là 0,1 hoặc 1/10. Điều này có thể được thực hiện với một chuỗi vô hạn (mà tôi không thể thực sự bị làm phiền), nhưng bất cứ khi nào một máy tính lưu trữ 0,1, nó không chính xác số này được lưu trữ.

Nếu bạn có quyền truy cập vào một máy Unix, thật dễ dàng để thấy điều này:.

Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> 0.1 
0.10000000000000001 
>>> 

Bạn sẽ muốn được thực sự cẩn thận với các bài kiểm tra bình đẳng với phao nổi và đôi, trong bất cứ ngôn ngữ bạn đang ở trong

(Như ví dụ của bạn, 0,2 là một số khác không thể lưu trữ trong nhị phân IEEE, nhưng miễn là bạn đang kiểm tra sự bất bình đẳng, chứ không phải là cân bằng, như p < = 0,2, thì bạn sẽ ổn .)

5

Một C đơn giản mà caug ht me a while back,

char *c = "90.1000"; 
double d = 0; 
sscanf(c,"%f",&d); 
printf("%0.4f",d); 

>> 90.0999 

Đây là chức năng chuyển đổi góc trong DMS sang radian, không có trong trường hợp trên.

+2

Là một người dùng nặc danh được chỉ ra, với 'sscanf', trình biến đổi chuyển đổi" f "yêu cầu đối số' float', không phải 'double' (tuy nhiên," f "có nghĩa là' double' thành 'printf' - - có nó khó hiểu). Trình biến đổi chuyển đổi "lf" được sử dụng để làm cho 'sscanf' hoạt động với' double'. –

26
for(double d = 0; d != 0.3; d += 0.1); // never terminates 
19

bức tranh đáng giá ngàn lời nói - cố gắng rút ra phương trình f(k):
enter image description here
và bạn sẽ nhận được đồ thị XY như vậy (X và Y là về quy mô logarit).
enter image description here
Nếu máy tính có thể đại diện cho nổi 32 bit mà không làm tròn lỗi thì cứ mỗi k chúng ta sẽ nhận được 0. Nhưng thay vào đó, lỗi tăng lên với giá trị lớn hơn của k vì tích lũy lỗi dấu chấm động.

hth!

3

Đây là một trong số đó đã bắt gặp tôi.

round(256.49999) == 256 
roundf(256.49999) == 257 

đôi và nổi ..

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