-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redefine MODULO so MOD is its infix form, Vary behavior by refinement #843
Comments
Complaint on that particular point is a duplicate of: metaeducation/rebol-issues#1332 That ticket may provide some insight from Ladislav about why things are done the way they are. :-/ I don't have a grasp of the rationale behind mod, modulo, and remainder. It seems that Rebol2, R3-Alpha, and Red all have the same help, and says:
I'm not savvy enough about the applications of these to know the difference. The only thing I would really like to have is:
If there is some subtlety in behavior between MODULO and MOD which might be interesting, I think that needs to be done with a refinement. Now that we have SHOVE, you could even say x -> mod/alteration y and use it infix. It would be very helpful if you could reason through this and understand what exactly is going on, and what modulo means most usefully in programming languages by default. Then understand what this other property is. The comments might help:
I tend to think it's a good idea to look at what languages used by serious mathematicians use, so Haskell is always good to research: https://stackoverflow.com/questions/5891140/difference-between-mod-and-rem-in-haskell Sounds like it's up your alley! :-) |
I'm decidedly for About signs, some semi-random thoughts:
E.g:
while
|
Here is some more reading, from Red issues: red/red#2997 (discusses rounding modes, Some of their tests for modulo can be found with this search: https://github.com/red/red/search?q=modulo&unscoped_q=modulo
This is the main thing I want. (We might also consider But it would be good before making changes to ensure that the decisions aren't losing any functionality. As I've said, refinements are our new tool for getting there, since there is a way of calling infix with refinements now. So if you can take this all into account, integrate them into the tests, try not to wind up leaving out any code that's there today (but stick weird behaviors under less-used refinements)...I'm happy with whatever you decide! |
What if REMAINDER was implemented as mezzanine, based on DIVIDE and ROUND? |
Finally, I decided to not touch REMAINDER. MOD was bugged and its difference from MODULO apparently not interesting. ac52a71 defines MOD as the enfix form of MODULO |
Okay, sorry I lied, I'm going to get involved despite saying I wouldn't...mostly because tests broke and then I checked with Wolfram Alpha and it looks like the old answers matched. Don't be mad! :-)
Looking into it, it seems your definition almost agrees with Clojure/Haskell: Haskell and Scheme offer two functions, remainder and modulo – PL/I has mod and rem, while Fortran has mod and modulo; in each case, the former agrees in sign with the dividend, and the latter with the divisor.: https://stackoverflow.com/a/28027235/211160 Would it be okay to go with their choice? I think the argument is that remainder being the same sign as x probably makes it more predictable. Something about the tests is that if we compare not just Haskell/Clojure, but also Wolfram Alpha, and Google. Both of which say -3 mod -2 is -1. :-/ http://www.wolframalpha.com/input/?i=-3+mod+-2 Additionally they believe that -562949953421312.75 mod 1 is 0.25. By just setting MOD to enfix MODULO it seems to lose something a lot of people believe in...getting these fractional amounts. If anything, it looks like this commit may be backwards, that MOD was the one that was right and MODULO is the one no one else knows about or agrees with. Is there a reason not to flip it the other way? I think it seems like if your inputs aren't integers then you should be willing to do rounding vs. have the MOD do it itself...but then again, maybe MOD should always be integers and MODULO/FLOAT be specialized as FMOD (?) Really hard for me to say as I only use MOD on positive integers! |
@hostilefork let me explain. |
Hmmm, I see. Interesting. 562949953421311.25 is from the %mod.test.reb. I do see that Clojure seems to think this particular case is 0.25, where Rebol says 0.0:
Take the last 1 off before the decimal point, and Rebol modulo also says 0.25:
But add a 1 before the decimal point instead, and Clojure will say 0.0 too. Getting micro-technical for a moment, Clojure says of the two numbers:
So adding the decimal digit is enough to push it over bitwise into no longer having the resolution for the .25 at that point. Abstractly speaking, it seems like it may have the information to know in a case Rebol is reporting as 0.0, but if this really is just some edge case fringe behavior I'm very uninterested in whether it's optimal or not. :-)
It looked like a lot of tests had started failing, but I guess it looks like maybe these tests were picked specifically to be on an edge of distinction between MOD and MODULO. But if you wouldn't mind going over the tests and lining up the results are acting as you would expect, that would be helpful. You suggested https://github.com/metaeducation/ren-c/blob/master/tests/math/mod.test.reb Beyond the sign issues (and maybe the simpler/same rule for remainder as Clojure/Haskell), maybe making the tests make sense is as simple as knocking a digit off of those cases?? (Note: If you think there's a usefulness to the more complex remainder sign rule--since many languages do not have remainder anyway--I would say I really don't care about doing the same thing as Haskell and Clojure do that much. But the sign rule for mod seems pretty universal on Wolfram Alpha, Google, and your own suggestion...) |
About sign: I tried to be conservative, but if others agree with my humble opinion, then worst to change. About precision, note that "MONEY" (I hate that name!) works in much higher precision, so |
Looks like you took it out--but I'm in support of the feature if you think the code was better that way. I just need to have the tests working, because when the tests fail I don't know what I broke! So changing the tests is acceptable too. I put the MODULO tests into the %mod.test.reb file: They have some failures now:
Was 0.0 before, which I agree is likely a better answer. But this shows Clojure not rounding:
And for whatever it's worth, Haskell doesn't either. (Their default mod is integers only, so the mod' operation is something you have to load in from a package Data.Fixed that isn't included by default. Backticks are how you make a function invocation infix in Haskell.)
Still your call. But I feel like if the code was written and has a point, we probably don't want to throw it out--just didn't want two separate operations. So either it should be the default behavior of MOD with /UNCHECKED (or a better name) as the refinement to ask for not doing the rounding, or the rounding should be optional and asked for as /CHECKED. |
After some experiment I'm skeptical about code trying to detect when remainder is 'almost zero' w.r.t. operands, because there's always some arbitrariness in that. |
Sounds good. For the sake of arguing that we didn't throw anything out that was there before...can the "almost zero" detection be put under a refinement? MOD/ADJUSTED might be better than MOD/CHECKED... I dunno, whatever name is fine. |
Well, if so maybe worth to set |
Or better other way around, in line with old behaviour: |
Note: Was resolved with |
The text was updated successfully, but these errors were encountered: