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)

Đâ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

1 Like

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

1 Like

ko thì bạn thử in biểu thức kia ra thay vì gán vào biến xem sao

1 Like

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

1 Like

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

1 Like

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

1 Like

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

3 Likes

Mình đang đọc thử, cảm ơn bạn.

Dùng decimal thử xem.

1 Like

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.

2 Likes
#include <iostream>

int main()
{
    double x1,x2,y1,y2;
    x1=106.036;
    y1=20.56213;
    x2= 106.03519;
    y2=20.562710;
    double pre = x1*y2-y1*x2;
    std::cout << pre << "\n";
}

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ằng double 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ó.

1 Like

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à:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?