01/10/2018, 09:26
Phép tính đơn giản nhưng kết quả sai?
Xin chào anh/chị và các bạn , mình đang gặp LỖI với phép tính sau :
float x1,x2,y1,y2;
x1=106.036;
y1=20.56213;
x2= 106.03519;
y2=20.562710;
double pre = x1y2-y1x2;
Kết quả khi in ra : pre=0.078125.
Trong khi kết quả chính xác phải là: pre=0.07815620.
Đây là nguyên nhân chính khiến các phép tính của mình bị sai lệch rất lớn phía sau.
Mong anh chị và các bạn giúp mình tìm ra nguyên nhân và cách khắc phục.
(mình lập trình trên phần mềm processing, với kiểu double cỡ 8 byte)
Bài liên quan
Đây là kết quả tính trên google, mình rất bí trong trường hợp này !
Mình không hiểu nữa, có lẽ như kiểu float không biểu diễn được đầy đủ. Nếu thay kiểu x1, x2,… bằng double thì kết quả cho ra như bạn mong đợi.
http://cpp.sh/8cku
Mình đã thử thay x1,x2,x3,x4 là kiểu double nhưng kết quả vẫn không khá hơn ?!
pre thậm chí bằng: 0.078269
bạn thử long double đi
ko thì bạn thử in biểu thức kia ra thay vì gán vào biến xem sao
mình đã thử rút ngắn để nó “có vẻ” vừa với float nhưng kết quả vẫn lệch :
x1 = 106.036; y1 = 20.56213; x2 = 106.0351; y2 = 20.56271;
bạn thử in từng cái ra xem bên trong nó bằng bao nhiêu sau đó in cả biểu thức ra xem sao
Với cách in trực tiếp : Kết quả vẫn là pre=0.07826.
Với Long Double : procesing không có kiểu dữ liệu này. Hơn nữa mình chỉ muốn dừng lại ở Float hoặc Double để phù hợp với vi điều khiển !
dung %lf để in long double thử đi nếu vẫn sai thì tính cách khác
Kiểu float chỉ cho lưu được 6 chữ số sau dấu phẩy.
Kiểu double thì được thừa đến 7
Mình tiếp tục rút ngắn nhưng kết quả lệch là “quá lớn”
float x1,x2,y1,y2;
x1 = 106.036;
y1 = 20.5621;
x2 = 106.0351;
y2 = 20.5627;
double pre = x1y2-y1x2;
với X,Y double: pre=0.0821275
với XY float :pre= 0.0820312
Kết quả chung cuộc trên google cho phép tính trên :
pre=0.08212748999.
Như vậy : kể cả khi xóa các số phía sau thì Float vẫn không phù hợp ?
(Mình nghĩ việc xóa chỉ là cho các số sau dấu phảy =0 )
Hơn nữa mình sẽ không thể tiếp tục xóa vì các giá trị kinh độ-vĩ độ đều phải có ít nhất 6 số sau dấu phảy, các kết quả mô phỏng phía trên khiến mình bị lệch hàng trăm km, và không thể sử dụng trên các dòng vi điều khiển AVR.
Bạn có đọc trong đây chưa:
https://processing.org/reference/float.html
“Floats are not precise, so adding small values (such as 0.0001) may not always increment precisely due to rounding errors. If you want to increment a value in small intervals, use an int, and divide by a float value before using it. (See the second example above.)”
Bạn thử làm như cách họ gợi ý xem sao
Mình đang đọc thử, cảm ơn bạn.
Dùng decimal thử xem.
Bạn gợi ý cho mình chứ , “decimal” mình chưa từng nghe qua (mình ở bên Tự Động Hóa)
Vẫn chưa được à.
Nếu kẹt quá thì cheat đi.
Nhân cho 1000 trước:
x1 *=1000;
y1 *=1000;
…
sau khi tính pre thì chia lại cho 1.000.000
Xem kết quả thử coi có được không.
kết quả là 0.0781562
làm gì mà “pre thậm chí bằng: 0.078269”?? Có chuyển về double chưa vậy??
Find&replace, tìm
float
thay bằngdouble
hết là xong. Còn bên trong thư viện tính toán mà nó dùng float thì tìm xem thư viện nó cho xài double ko, chắc chắn phải có.Bạn “gioi” Mình thử rùi, mình cho XY nhân với 1000000 để đảm lấy 6 số phía sau, lưu với long, rồi chia lại và ép kiểu nhưng kết quả vẫn giống hệt với cách dùng float, có lẽ là do float không chứa nổi . Kiểu này phải tìm phương pháp thủ công để tính số trên hệ nhị phân.
Bạn “tntxtnt” : Mình nhân trên procesing của mình nó vậy mà:
vậy cái này do lỗi phần mềm Processing gì rồi, chắc bên trong nó tính bằng float nên vậy. Đốt phần mềm đó đi @_@
vô cái forum hay github hay gửi email cho Processing chửi họ sao phép tính đơn giản xài
double
lại cho kết quả tầm bây.