Nie przedłużając, problem wygląda tak:
Jaki jest wynik z dzielenia i ile wynosi reszta z dzielenia następujących liczb:
-12 przez 5
12 przez -5
Wg mojej, bądź co bądź pozyskanej w szkole podstawowej, wiedzy wyniki powinny być takie:
-12 przez 5 = -2 i reszty -2
12 przez -5 = -2 i reszty 2
Natomiast podręcznik Krzysztofa Kłaczkowa, Marcina Kurczaba i Elżbiety Świda "matematyka; podręcznik do liceów i techników, klasa I, zakres podstawowy i rozszerzony" (wydanie I, 2002) twierdzi że wyniki są takie:
-12 przez 5 = -3 i reszty 3
12 przez -5 = -2 i reszty 2
Autorzy przy okazji przywołują definicję:
Liczba całkowita a przy dzieleniu przez liczbę całkowitą b != 0 daje resztę r (r należy do N) wtedy i tylko wtedy, gdy istnieje taka liczba k należąca do C, że a = k * b + r, gdzie 0 <= r < |b|. Symbol |b| oznacza wartość bezwzględną liczby b.
Nasza polska Wiki (polecam ten art btw) ma odrobinę różną definicję reszty z dzielenia liczb całkowitych:
Jeżeli a i d są liczbami całkowitymi, gdzie d nie jest zerem, wtedy reszta jest liczbą całkowitą taką, że a = qd + r dla pewnego q i przy 0 <= |r| < |d|. Kiedy definiujemy w ten sposób istnieją dwie możliwe reszty. Na przykład, dzielenie -42 przez -5 może być wyrażone jako
-42 = 9*(-5) + 3
albo
-42 = 8*(-5) + (-2).
Tak więc resztą jest 3 lub -2.
Więc OK, rozumiem że w podręczniku do liceum używają uproszczonej definicji tak aby nie mieszać ludziom w głowie od początku mówiąc że "istnieją dwie reszty z dzielenia".
Ale w przypadku języków programowania nie można mówić o dwóch różnych wynikach dzielenia czy dwóch różnych resztach z dzielenia, więc powstaje pytanie - jak to jest w przypadku różnych języków? W przypadku języków kompilowanych jest dodatkowe pytanie: jak to wygląda na różnych architekturach?
Podczas moich testów otrzymałem następujące wyniki (wyniki w formacie A Br, C Dr, gdzie -12 / 5 = A i reszty B i 12 / -5 = C i reszty D):
Podręcznik : -3 3r, -2 2r
Intuicja : -2 -2r, -2 2r
C, gcc, x86-64: -2 -2r, -2 2r
C, gcc, sparc : -2 -2r, -2 2r
PHP, x86-64 : -2 -2r, -2 2r
Python, x86-64: -3 3r, -3 -3r
Ruby, x86 : -3 3r, -3 -3r
Perl, x86-64 : -2 -2r, -2 2r
Jak widać wyniki są bardzo podobne, ale jednak różne (Python, Ruby). Natomiast niewątpliwie ciekawe.
By the way...
There are more blog posts you might like on my company's blog: https://hexarcana.ch/b/
A kto ma rację? Cóż, to zależy od definicji, więc zapewne każdy ma własną ;>
Zachęcam do przetestowania innych języków / architektur i podzielenia się wynikami!
UPDATE: Warto rzucić okiem tutaj, jest tam rozpiska jaki język programowania którą wersje wyników poda (bardziej ogólnie ofc) (via kross12 z komentarzy na wykopie)
UPDATE 2: W czym jest napisany "kalkulator" w wyszukiwarce Google? No idea, ale pewna podpowiedź już jest:
(-12) % 5 w Google (spoiler: 3)
12 % (-5) w Google (spoiler: -3)
UPDATE 3: Bardzo ciekawy i warty przeczytania wpis nawiązujący do powyższego tematu: "Na ogólne życzenie publiczności"
Comments:
Dzisiaj rano przypadkiem trafiłem w pewnej książce na wyjaśnienie:
http://gigamonkeys.com/book/numbers-characters-and-strings.html - przypis 10
Wynika z tego, że w C nie było ustalonej wersji aż do C'99, a w różnych językach operator % robi zupełnie co innego. Tłumacząc z tamtej książki definicje dwóch reszt (rem i mod):
floor(x/y)*y + mod (x,y) == x
truncate(x/y)*y + rem(x,y) == x
Gdzie floor to zaokrąglanie w stronę minus nieskończoności, a truncate - zaokrąglanie w stronę zera.
Korzystałem z funkcji MOD(X,Y). Moje intuicyjne pojęcie reszty, zwłaszcza pojęcie modulo, "od zawsze" obejmowało okresowość funkcji (przy ustalonym dzielniku). To pewnie z tego powodu, iż okresowość jawiła i nadal jawi mi się ogólnie potrzebniejsza niż reszty różnych znaków. Poza tym definicja reszty zawsze nieujemnej prostsza jest od definicji zacytowanej z Wikipedii, a na dodatek daje jednoznaczny wynik; dla zwolennika brzytwy Ockhama to wystarczy. KISS!
Byłem ciekaw, jak zapatruje się na to prowadzący zajęcia i czy kiedyś miał podobny problem. Otóż nie miał, bo przecież "wiadomo, że modulo to reszta z dzielenia, a ta może być ujemna". Mieliśmy całkowicie odmienne intuicje.
http://codepad.org/g1CnuMv8
+ man fmod:
"if y is non-zero, the result has the same sign as x and magnitude less than the magnitude of y"
w pythonie też jest fmod, a co do wbudowanego operatora:
"The modulo operator always yields a result with the same sign as its second operand (or zero); the absolute value of the result is strictly smaller than the absolute value of the second operand"
http://codepad.org/4B1qKZkT
Zastanawiające natomiast jest zachowanie haskella:
http://codepad.org/HXBAy2xk
http://nopaste.gamedev.pl/?id=4378
Dla pierwszej definicji (książkowej) mamy:
-12 przez 5 = -3 i reszty 3 czyli -12 należy do jednej klasy abstrakcji.
Działając wg definicji Wikipedii mamy:
42 = 9(-5) + 3
albo
-42 = 8(-5) + (-2)
Czyli 42 należy do dwóch różnych klas abstrakcji, co oczywiście nie może być prawdą. Czyli druga definicja jest błędna.
-12 / 5 = -3 r 3
12 / 5 = 2 r 2
?? Gdzie tutaj logika?
Drogi kolego, druga część twojego rozumowania jest ciut błędna.
Tam nie ma definicji, tam są dwie alternatywne możliwości.
Niech a equiv b (mod n).
Wszystko zależy od przyjętej definicji reszty.
Jeśli przyjmiemy, że b ma mieć ten sam znak co a, to
cytowaną przez Ciebie definicję drugą i 9 rozłącznych klas abstrakcji.
Jeśli przyjmiemy że b ma być zawsze >= 0, to
mamy pięc rozłącznych klas abstrakcji.
1. Nie rozmawiać o |b|
2. NIE rozmawiać o |b|
-2 -2r, -2 2
:-D
Skoro nie znacie podstaw, to już jakiekolwiek wywody na bardziej zaawansowane zagadnienia mijają się w Waszym przypadku z celem. :P
W matematyce są definicje (prawa) lub aksjomaty działań.
W dzieleniu z resztą definicja jest JEDNOZNACZNA!!!
RESZTA należy do zbioru liczb NATURALNYCH, dla tych co nie wiedzą co to za zbór liczb....
..są to liczby WIĘKSZE od ZERA i CAŁKOWITE!!
Czyli reszta MUSI być większa od ZERA!
koniec kropka. :P
Otóż...
W matematyce odnosi się za pomocą liczb rzeczywistość. (upraszczając)
I dzieląc np. linę długość powiedzmy 14 metrów na 4 odcinki. (zakładając, że mają do być odcinki o stałych wielkościach i zawierać się w zbiorze liczb całkowitych)
Dostaniemy ZAWSZE 4 odcinki po 3 metry i 2 metry 'reszty'.
Nie ma możliwości, aby dostać 4 metrowe odcinki i 'pożyczyć' skądś 2 metry liny.
Dlatego dzielenie liczb całkowitych z resztą, daje zawsze resztę dodatnią.
Prosiłbym bez osobistych wjazdów, trzymajmy dyskusje na poziomie ;>
@Tobi
Hehe dobree ;> (btw chyba w oryginale /b/ było ne ?;>)
@Jurgi
Chyba chwilę przed tobą dorzuciłem to do postu jako update 3 ;> (tak, nadal przeglądam referery ;>)
Świetny post btw gość napisał ;>
@all
Sporo się dowiedziałem z komentarzy ;>
Mimo, że pracujesz na Windowsie, to nigdy nie widziałem ani linijki kodu w np. C# (jakieś uprzedzenia?) ;> Tak mnie to zaciekawiło jakoś, szkoda, że nie mam tu VS'a, bo bym sprawdził co on na to.
Małe sprostowanie: pracuje w pracy na Windowsie ;> W domu na głównym kompie mam Kubuntu, a na lapku OSX'a ;> Raczej staram się nie ograniczać jeśli o OS chodzi ;>
Co do czemu nie widziałeś C#. Cóż, akurat ten język cały czas na liście "ToDo" u mnie leży hehe ;>
Natomiast to good idea żeby sprawdzić i C# i Jave. Zrobię to potem ;>
-12 / 5: -2 r -2
12 / -5: -2 r 2
BTW bardzo ciekawy problem, zapytam się jutro matematyczki co o tym sądzi, jak będzie miała czas :)
Wybacz, ale głupoty wypisujesz, po pierwsze bzdura ideowa:
"W matematyce odnosi się za pomocą liczb rzeczywistość. (upraszczając)"
Pomijając poprawność językową tego zdania, matematyka jest narzędziem, opis "rzeczywistości", czyli jak mniemam fizycznego jej modelu to tylko jedno z zastosowań matematyki, a zastosowania są nieograniczone.
Po drugie
"RESZTA należy do zbioru liczb NATURALNYCH, dla tych co nie wiedzą co to za zbór liczb...."
To ciekawe co mówisz, bo wg. algebry abstrakcyjnej reszta jest tylko operatorem matematycznym, a te mogą być określone na każdym zbiorze tworząc razem z nim i innymi operatorami strukturę - czy to będzie pierścień czy kraty czy whatever, zawsze (jak w programowaniu) chodzi o dane + operacje, a operacje można przeciążać :P (jak tłumaczyć matmę koderowi? :D)
Na czym polega problem z resztą - właśnie na określeniu na jakich danych operujemy, ale obie przytoczone definicje są poprawne :)
(-12) % 5 = -2
12 % (-5) = 2
(-12) / 5 = -2
12 % (-5) = 2
12 / (-5) = -2
Więc w sumie to kwestia założeń. Wynik jest zawsze taki sam i można go dalej używać choćby w rachunkach modulo.
-12 / 5 = -2,4
12 / 5 = 2,4
to oznacza, że 4/10 = 2/5 stąd zawsze reszta będzie dodatnia a znak ustalany jest na końcu więc chcąc być bardziej poprawnym o ile znajdujemy równanie -12 == (-2 * 5) - 2 to brakuje tu ostatniego etapu (wyciągnięcia wspólnego czynnika przed nawias) czyli wartość bezwzglęna z -2 to 2 :D więc naszą resztą zawsze jest wartość dodania r = |r'| gdzie r' to pozostała część równania. Po wyciągnięciu czynnika przed nawias (-1) otrzymamy:
-12 = -((2*5) + 2)
Kolejny przypadek 12 / -5
12 == (-2 * -5) + 2 - w tym przypadku r = |r'| więc r = 2 bo r' = 2 => tu nie ma potrzeby wyciągać -1 bo znajduje się tylko po jednej stronie równania (przed znakiem "+") czyli mamy dokładnie pełną i zgodną formę i po przemnożeniu -2*-5 > 0
tak samo jak (2*5) > 0.
Taka moja hipoteza.
Add a comment: