World: r3wp
[!REBOL3-OLD1]
older newer | first last |
BrianH 9-Nov-2009 [19487x2] | Right now, all op! functions redirect to corresponding action! functions. // redirects to REMAINDER, which is why we need it. |
When you run into major errors like PeterWood's above, report them. Since MOD and MODULO are mezzanine, they can be fixed right away by someone with the right math knowledge. Ladislav? | |
Geomol 9-Nov-2009 [19489x2] | I'm not questioning, that we need a modulus function (REMAINDER). I'm questioning, if we really need 3 of them. If REMAINDER doesn't do, what it's supposed to, then I would fix that instead of adding 2 new functions. |
Brian, no they can't be fixed right away. See my example with round/floor above. That's the way to calculate a modulus, and it doesn't work. :) | |
BrianH 9-Nov-2009 [19491x3] | From what I can tell from the code though, modulus and remainder aren't exactly the same concepts. But, I don't have that math knowledge. The mezzanines claim to do extra error checking, but I don't know what part of their code does that. |
If there is an error, and the math within the functions makes sense, then there is an error in the underlying operators somewhere that needs to be tracked down. Ladislav? :) | |
From your code, it looks like this is the problem: >> round/floor 3.3 / 1.1 == 2.0 >> 3.3 / 1.1 == 3.0 1.1 and 3.3 aren't exactly representable in IEEE754 encoding, so the 3.0 value you see is actually a little less than 3.0. | |
Rebolek 9-Nov-2009 [19494] | Brian, when I try round/floor 3.3 / 1.1 it returns 1.1 (2.100.94.3.1 on XP) |
BrianH 9-Nov-2009 [19495] | If you want exact decimal math, you have to switch to a different underlying representation, such as that used by money!: >> round/floor $3.3 / $1.1 == $3 >> $3.3 / $1.1 == $3.0000000000000000000000000 |
Geomol 9-Nov-2009 [19496] | I think, I see, what happening now. If 3.3 / 1.1 is just below 3.0, then the round/floor will return 2.0, which is ok. So my example might not be a real problem after all, unless it give different results on different platforms. |
BrianH 9-Nov-2009 [19497] | Bolek, are you sure you put in /, instead of //? Cause that sounds extra weird, since I am also testing on XP. |
Rebolek 9-Nov-2009 [19498] | Ah, my stupid fault :) >> round/floor 3.3 1.1 == 1.1 :) |
Geomol 9-Nov-2009 [19499] | Hm, the round/floor way probably shouldn't be used, when dealing with decimals. It should then just use the C function, fmod (). |
BrianH 9-Nov-2009 [19500x3] | Geomol, that inaccuracy is built into the standard, and floating point hardware tends to follow that standard. It's a side effect of the fact that IEEE754 floating point numbers are internally base 2, and in base 2 the decimal value 0.1 is an infinite number just like 1/3 is in base 10. |
And if you look at the source of MOD and MODULUS, neither of them uses round/floor :) | |
Sorry, MODULO, not MODULUS :) | |
Geomol 9-Nov-2009 [19503x3] | Brian, I know about IEEE754! :) |
I wrote much of the documentation about it. | |
I just tested, the C function, fmod (3.3, 1.1), also returns 1.1. :) | |
BrianH 9-Nov-2009 [19506x2] | I figured so, since if I knew about it it must be pretty basic :) |
I think that the difference between // and MOD is in how they handle negative numbers. Modulus (as a math concept, as I recall) isn't defined for negative numbers at all. Programming languages tend to punt when it comes to this, so // works the most common way, and MOD converts it to the next most common way. | |
Geomol 9-Nov-2009 [19508] | The reason is understandable too. When the two decimals tested can be divided without remainder (the remainder comes close to zero), we can't use the result. It's because the division can be on either side of zero, so the rounding will give zero or -1.0. |
BrianH 9-Nov-2009 [19509x3] | >> $3.3 // $1.1 == $0 |
The $ in this case just being a sigil for a different numeric representation that works better in this kind of situation. | |
(Good work on that, Ladislav!) | |
Geomol 9-Nov-2009 [19512x2] | I also tested, that it takes equal amount of cpu time to do this in C, where a and b are of type double: fmod (a, b) or a - floor (a / b) * b Same can be said for integers, where we would use % in C. |
I conclude, it makes sense to drop MOD and MODULO, and then use the calculation using floor for both integers and decimals. It will give the mathematically best result, and it will perform as good as using % and fmod in C. | |
BrianH 9-Nov-2009 [19514x3] | MOD and MODULO are supposed to be different from // for *negative* numbers. |
If you look at the source for those functions, you will see that MOD calls // internally, and MODULO calls MOD. | |
Neither call floor (unless // calls it internally). | |
Geomol 9-Nov-2009 [19517] | And if you look in HELP MODULO, it looks like a hack to fix some problem: Wrapper for MOD that handles errors like REMAINDER. Negligible values (compared to A and B) are rounded to zero. |
BrianH 9-Nov-2009 [19518x3] | Yup. Which is where my math knowledge left off. I can see the math they use, but not why it is necessary. |
I get MOD, I think: It's that negative values thing. MODULO seems to deal with the epsilon, afaict. | |
Ladislav wrote them, iirc. If he thinks they're necessary I'll take his word for it :) | |
Geomol 9-Nov-2009 [19521] | Ops, I said something wrong, when saying, the division can be on either side of zero. The division is of course close to a whole number, but can be on either side of that number, so the rounding can be that number (if the result lie above) or one below that number (if the result is below). Using ROUND instead of ROUND/FLOOR solves it. |
BrianH 9-Nov-2009 [19522] | Use the SOURCE, Luke. ROUND isn't used at all. |
Geomol 9-Nov-2009 [19523] | I just say Ladislav popping in. Ladislav, if you don't wanna read all, my question simple is, if we need all of REMAINDER, MOD and MODULO? |
BrianH 9-Nov-2009 [19524] | Although perhaps it should be. MOD and MODULO were written when ROUND was mezzanine. Now that ROUND is native, perhaps MOD and MODULO could be optimized by someone who understands the math (not me). |
Geomol 9-Nov-2009 [19525] | (And maybe you're not the one to answer this question.) :) |
Ladislav 9-Nov-2009 [19526] | When implementing Round as mezzanine, I needed MOD to do it, and Gregg thought it might have been useful to make it available; |
BrianH 9-Nov-2009 [19527] | Good enough :) |
Ladislav 9-Nov-2009 [19528x4] | Remaninder (//) is handling operands as "exact", MOD uses some "rounding", MODULO is more "standard" and uses even more rounding |
the difference is as follows: >> mod 0.3 0.1 == -2.77555756156289e-17 >> remainder 0.3 0.1 == 0.1 | |
>> modulo 0.3 0.1 == 0.0 | |
The fact is, that MOD was necessary for positive values of B only, so there is no provision for the negative ones | |
Geomol 9-Nov-2009 [19532] | So the difference is only, when the division give a remainder close to zero. Example of same results: >> mod 0.3 0.2 == 0.1 >> remainder 0.3 0.2 == 0.1 >> modulo 0.3 0.2 == 0.1 And then there are some differences, when dealing with negative numbers. |
BrianH 9-Nov-2009 [19533x2] | Should there be? And is more optimization possible? |
Should there be? -> Should there be provision for the negative ones, Ladislav? | |
Ladislav 9-Nov-2009 [19535x2] | It is even possible to axe the MOD function, ask Gregg, what he thinks about it |
(or make it "hidden", if the MODULO function remains) | |
older newer | first last |