mojaSymfonia FORUM
https://forum.mix-soft.pl/

Symfonia błędnie oblicza działania matematyczne
https://forum.mix-soft.pl/viewtopic.php?f=15&t=683
Strona 1 z 1

Autor:  Benji_Pete [ 2009-03-16, 16:13 ]
Tytuł:  Symfonia błędnie oblicza działania matematyczne

Zaintrygowała mnie pewna sprawa w Symfonii Handel 2006c

Piszę raport, gdzie potrzebuję się dowiedzieć, czy wynik dzielenia jest całkowity czy ułamkowy.
Rozwiązuje to reszta z dzielenia, czyli operator %.
Jednak gdy podam liczby zmiennoprzecinkowe (float) to wywala błąd, więc rozumiem, że operator pracuje na liczbach całkowitych.

Więc zabieram się do ominięcia operatora, korzystając z funkcji zaokrąglającej Round.

Oto przykład, gdzie mam błąd:

Kod:

float liczba1 = 4.2
float liczba2 = 1.4
float wynik = liczba1/liczba2
FLOAT rwynik = Round(wynik,0)
if  (wynik-rwynik)==0 then
   Message "Brak reszty - OK"
else
   Message "Jest reszta"
endif
Error ""


Komunikat, który mi wyskakuje to "Jest reszta". Gdy liczby są całkowite działa to prawidłowo, jeśli zmiennoprzecinkowe to też działa, ale ten przykład akurat NIE!!
Załamać się idzie.
Zmienna wynik w powyższym przykładzie wyniesie 3.0, zaokrąglony całkowitej jako zmienna też wyniesie 3. Więc 3-3 jest 0 i powinno się pokazać "Brak reszty". Jak dam liczby np. 5.6 i 1.4 to wynikiem będzie całe 4 i pokazuje dobrze. Jak dam 3.9 i 1.3 to też jest dobrze.

ZNALAZŁEM drugi przypadek. To para liczb 3.3 i 1.1

Proszę wklejcie ten krótki raport do Symfonii i przekażcie wyniki, bo się idzie pochlastać.

Dziękuję z góry

Zamiast if..endif dałem select case..end select - niestety to samo w przypadku tych dwóch par liczb. Być może jeszcze jakieś istnieją :(

Kod:

Select Case (wynik-rwynik)
   Case 0
      Message "Brak reszty - OK"
   Case Else
      Message "Jest reszta"
EndSelect


Autor:  rafal [ 2009-03-16, 16:37 ]
Tytuł: 

Kod:
int Sub CzyJestReszta(dloat liczba1, float liczba2)

   int temp   
   wynik = liczba1 / liczba2

   if temp != wynik then CzyJestReszta = 1

endsub


funkcja zwraca 1 jeżeli jest reszta

Autor:  wrob [ 2009-03-16, 17:10 ]
Tytuł: 

Moze warto na wykładach o systemie binarnym czasem sluchac prowadzacego jak mowi o reprezentacji ulamkow dziesietnych w systemie binarnym

dla przykładu 1.4 (dec) to 1.0110(0110)(bin) czyli ulamek okresowy wiec nie jest dokładnie zapisywane jako 1.4 w kompie

zreszta 0.3 ma podobne rozwiniecie co prawda nie okresowe ale za to dość długie

stad moze i handel zle liczy bo procedury na liczbach float zawsze maja takie problemy

stad przy pisaniu takich funkcji dobra praktyka jest zaokraglać

if (round(wynik,2)-round(rwynik,2))==0 then

wiecej na ten temat tutaj:

http://support.microsoft.com/kb/78113/pl


PS a funkcja rafala nie dziala - bo chyba temp nigdzie nie jest w niej obliczany :(

Autor:  Benji_Pete [ 2009-03-16, 17:14 ]
Tytuł: 

Dziękuje rafal, ale chyba funkcja jest niepełna. Co przedstawia zmienna temp??
Przyznacie, że w moim kodzie powinno być OK, skoro dla szeregu innych parametrów jest dobrze to dlaczego nie jest w przypadku pary 4.2, 1.4 i 3.3 i 1.1?

Autor:  rafal [ 2009-03-16, 17:18 ]
Tytuł: 

Kod:
int Sub CzyJestReszta(float liczba1, float liczba2)

    int temp   
    float wynik = liczba1 / liczba2
    temp = wynik
    if temp != wynik then CzyJestReszta = 1

endsub

temp jest typu int.

po przypisaniu wyniku dzielenia do temp w tempie przechowywana jest część całkowita wyniku dzielenia.

Błędem jest uzycie Rounda bo to zaokragla a nie obcina część dziesiętną.[/code]

Autor:  Benji_Pete [ 2009-03-16, 17:34 ]
Tytuł: 

Masz rację wrob. Próbowałem w Delphi tego samego przykładu i..... to samo. Też uznał, że wyniki tych obliczeń dla 4.2 i 1.4 są różne - czyli jest reszta, choć jej nie ma.

Problem rozwiązałem mnożąc argumenty przez 10, gdyż nie będą to liczby po przecinku więcej jak 1. Ciekawa sprawa

Jeszcze raz dziękuję Panowie.

Pozdrawiam.

Autor:  rafal [ 2009-03-16, 18:05 ]
Tytuł: 

kolejne próby :

Kod:
int Sub CzyJestReszta(float liczba1, float liczba2)

    float fwynik = liczba1 / liczba2
    int itemp = fwynik: float ftemp = fwynik
    if ftemp != fwynik then    
      CzyJestReszta = 1
   else
      CzyJestReszta = 0
   endif

endsub

Autor:  Nietoperz82 [ 2009-03-18, 10:24 ]
Tytuł: 

Benji_Pete pisze:
Przyznacie, że w moim kodzie powinno być OK


Nie jest przykład OK. To są liczmy zmienno przecinkowe a one rządzą się swoimi prawami!!! Trzeba je znać

oto drobna modyfikacja Twojego kodu i już jest prawidłowo.

Kod:
float liczba1 = 4.2
float liczba2 = 1.4
float wynik = liczba1/liczba2
float rwynik = Round(wynik,0)

if  round(wynik - rwynik,10) == 0 then
    Message "Brak reszty - OK"
else
    Message "Jest reszta"
endif


Wystarczy że stwierdzisz ile miejsc znaczących chcesz porównywać.

Strona 1 z 1 Strefa czasowa UTC+1godz. [letni]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/