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.

Reply via email to