Błędy obliczeniowe na liczbach float i double

0

Czesc. Mam tutaj taki kawalek kodu:

              //movementSpeed=0,0625; 
              //posX i posZ sa typu float, probowalem tez z double. 
    public void move(Grid grid){
        if ((posX > 0 && xSpeed.currentValue() == -1) || (posX < grid.getxSize() - 1 && xSpeed.currentValue() == 1))
            posX += xSpeed.currentValue() * movementSpeed;
        if ((posZ > 1 && zSpeed.currentValue() == -1) || (posZ < grid.getzSize() && zSpeed.currentValue() == 1))
            posZ += zSpeed.currentValue() * movementSpeed;
        //System.out.println(posX + " " + posZ);
        //strafing
        if (posX % 1 == 0 && posZ % 1 == 0){
//tutaj ewentualnie zakrecam wezem

Kalkuluje on nastepna pozycje mojego weza bazujac na jego kierunku. Problem w tym, ze jesli ustawie "zla" wartosc movementSpeed na przyklad 0,1, w posX i posZ zacznaja pojawiac sie male bledy. Zwykle by mi to nie przeszkadzalo, ale w tym wypadku moje sprawdzanie czy waz jest na srodku pola przy pomocy modulo zawodzi.Zdaje sobie sprawe ze sa one spowodowane zaokraglaniem przy pracy na liczbach zmiennoprzecinkowych.

Ale teraz, probujac przyciac posX uzywajac tej metody:
posX = Math.round(posX * 1000) / 1000
Bledy pojawiaja sie juz na trzecim miejscu po przecinku, co jest niedopuszczalne.

Wartosci w xSpeed i zSpeed maja tylko 3 wartosci, 0,1,-1
Dziwi mnie wiec dlaczego dzialanie takie jak 0,1 * 1 nie daje czystego wyniku, ale 0,10000cos tam cos tam.

Czy macie na to jakis sposob?

0

Może pomóc Ci BigDecimal, poczytaj o reprezentacji tych liczb w systemie binarnym i dowiesz się o przyczynie tej sytuacji

1

Zrób to na intach, albo nie przejmuj się, bo na pewno aż taka dokładność nie jest ci potrzebna.

sprawdzanie czy waz jest na srodku pola przy pomocy modulo zawodzi

więc zrzutuj sobie tego floata na int, albo użyj jakiejś funkcji do zaokrąglania.

Bledy pojawiaja sie juz na trzecim miejscu po przecinku, co jest niedopuszczalne.

Czy na prawdę potrzebne ci są aż tak dokładne obliczenia przy SNAKU? Do takiej gry nawet nie trzeba używać typów zmiennoprzecinkowych.

I pamiętaj, że przy porównywaniu typów zmiennoprzecinkowych, ze względu na ich ograniczoną dokładność (co z resztą odkryłeś), powinno się je porównywać z pewnym przybliżeniem. Tzw. epsilon.
Czyli coś w tym rodzaju

const float epsilon = 0.00001f;
float a, b;
...
if(abs(a-b)<=eplison)
0

Dzieki za podpowiedz co do porownywania typow zmiennoprzecinkowych.

Jesli chodzi o wszystkie rzutowania i inty to niestety nie mam takiej możliwości. Potrzebuje dokładności zmiennoprzecinkowej ponieważ waz jest renderowany w 3d, uzycie wiekszych liczb spowoduje twarde skoki miedzy polami.

Chcialbym tez uniknac klas takich jak BigDec.
Probowalem juz zaokraglanie nie zadzialalo bo potrzebuje go do n-tego miejsca po przecinku, a jedyne co znalazlem to przycinanie o którym wcześniej wspomniałem.

usunięcie cytowania całego poprzedniego posta - fp

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0