On Thu, 23 Oct 2003, Daisuke Maki wrote: > Okay, I feel stupid asking this, but I have a question about a basic > function, "mod". > > My ported computations from CC become all wrong if I use Perl's built-in > "%" operator. After a few trial and errors, it seemed like when CC mentions > > R = N mod M > > it's actually computing a fractional number. For example, 15.1 mod 4 > would be 3.1. If I take that to be true, most of my computations work. > However, now I'm having problems with taking a modulo of a negative value. > > Specifically, I'm trying to implement solar_longitude_after() (p.184) > function -- but it chokes when the difference between $phi and > solar_longitude($t) is a negative number to compute the value of $tau: > > $tau = $t + $rate * mod($phi - solar_longitude($t), 360); > > It seems like the output of mod() is expected to be something other than > what I've been computing... (The reason I suspect that is because the > solar terms that are generated by this function turns out wrong only if > $phi - solar_longitude($t) is negative ). > > Does anybody know how this is supposed to work? I tried a bunch of > things, but I just can't seem to get it right. Does anybody know how > this *should* be done?
Of the top of my head, I recall that CC defines their mod function's operation up front (in chapter 1? can't find my copy). I think they always want a positive floating point result. Perl's ($x%$y) will always give a positive result, but with $x and $y both truncated zeroward to an integer. POSIX::fmod will do floating point, but it gives negative results for negative $x. I think you need to roll your own. sub cc_mod { $_[0] - $_[1] * POSIX::floor( $_[0]/$_[1] ) } If you want to avoid use POSIX, floor is pretty easy: sub floor { int($_[0]) - ( int($_[0]) > $_[0] ) } Caveats: all code untested, no consideration of negative $y, comments about % don't apply if under 'use integer' where deliberately ambiguous C standard applies instead.