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/ |