Modulus

Rakstot par nesmukajiem datumiem, biju izmantojis šādu izteiksmi: $sundayEveningSpan = ((($now["wday"]-1)%7)*24*60*60);. Rezultātā mainīgais $sundayEveningSpan tiek uzstādīts (tam vajadzētu tikt uzstādītam) uz sekunžu skaitu starp šodienas plkst. 00:00 un šīs pirmdienas 00:00. Vārdu sakot, tiek aprēķināts, cik sekundes pagājušas šajā nedēļā.

Kā redzams, izteiksmē parādās operators %, kas atgriež izteiksmes $now["wday"]-1 vērtību pēc moduļa 7. Tas darīts tāpēc, ka PHP funkcijas GetDate() atgrieztajā masīvā wday lauks atgriež “Numeric representation of the day of the week: 0 (for Sunday) through 6 (for Saturday)”. Tātad svētdiena ir 0-tā diena, sestiena ir 6. diena. Tā kā man (un arī daudziem citiem latviešiem) nedēļa sākas ar pirmdienu, no dienas numura bija jāatņem vieninieks pēc moduļa 7, lai iegūtu pareizo piekārtojumu: pirmdienai 0, svētdienai (0-1) mod 7, kas vienāds ar 6 klasiskajā moduļu aritmētikā.

Tomēr izrādījās, ka šādi mana funkcija darbojas nekorekti. Izpētot tuvāk, secināju, ka PHP valodai arī ir savas īpatnības – modulis no negatīva skaitļa ir negatīvs. Tas arī oficiāli ir dokumentēts modulus operatora aprakstā. Tādēļ -1 % 7==-6, nevis 6, kā bija sagaidāms.

Lai novērstu šīs PHP īpatnības sekas, aizstājam -1 ar +6 (kas ir kongruenti pēc moduļa 7) un turpmāk nedēļas sākumu aprēķinām šādi: $sundayEveningSpan = ((($now["wday"]+6)%7)*24*60*60);.

Kā rāda testi, šāda pat problēma novērojama arī Visual Basic.Net un, ļoti iespējams, arī citās .Net valodās. Kā sacīts MSDN, “The result of x Mod y is the value produced by x – (x \ y) * y”. Tas nozīmē, ka gadījumā, kad pats x ir negatīvs, arī atgrieztais rezultāts būs negatīvs.

Tā, lūk. Atliek vien secināt, ka programmēšanas valodu veidotājiem ir vienalga, vai tiek saglabāta multiplikatīvās grupas pēc moduļa N un gredzena īpašība, kas tik svarīga ir matemātiķiem. Un tas, protams, ir tikai normāli – ja vajadzēs, vienmēr varēsim pieskaitīt 6 tā vietā, lai atņemtu 1.