[GRASS-dev] Overflow warning in r.mapcalc calculation

Rainer M. Krug Rainer at krugs.de
Thu May 16 05:42:25 PDT 2013


Glynn Clements <glynn at gclements.plus.com> writes:

> Rainer M Krug wrote:
>
>> > The round() function always returns an integer, regardless of its
>> > argument types. Integers are always 32-bit, so the result is limited
>> > to the range +/- 2147483647 (2^31-1).
>> 
>> True - but is there an equivalent function to round numbers outside the
>> integer range?
>
> No.
>
>> Would be useful. Looking at the functions in r.mapcalc, I can't
>> think of a way of doing this?
>
> outmap = eval(d = inmap % 1.0, dd = if(d < 0,d+1,d), inmap - dd + if(dd > 0.5,1,0))
>
> The added complexity is because the % operator returns a negative
> value for a negative numerator. Specifically, a % b = a - int(a/b)*b,
> where conversion to an integer rounds toward zero.
>
> It's not clear whether this behaviour is intentional or just how it
> turned out. This is how C's % operator is defined for integer
> arguments (for floating-point values, the fmod() library function
> behaves similarly).
>
> Also: r.mapcalc's % operator will fail if a/b overflows the range of
> an integer. That should be fixed
>
>> I just looked at the round function in xround.c, and it does not look to
>> complicated to modify round() to obtain have three more functions, aligned to the
>> R functions:
>
> One option is to modify round() to take a second argument (defaulting
> to 1), and have it return the first argument rounded to the nearest
> multiple of the second. The return type would be that of the second
> argument, i.e. round(x,1) rounds to the nearest integer and returns an
> integer, round(x,1.0) rounds to the nearest integer and returns a
> float, round(x,1e-3) would round to 3 decimal places (i.e. the nearest
> multiple of 0.001), etc.

Sounds like a sensible approach without adding to many new
functions. But I would actually split the two, i.e. have two more
arguments, where one specifies the type, 
and the other one the number of decimals to round to, i.e.

round(x, 0, "I") would be the default, rounding to whole number and
return an integer

round(x, 0, "F") would round to the next whole number but return an
float and

round(x, 0, "D") would round to the next whole number ad return a
double.

round(x, 2, "I") would return an error, while

round(x, 2, "D") would return a double, rounded to two decimals.

Cheers,

Rainer

-- 
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)

Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa

Tel :       +33 - (0)9 53 10 27 44
Cell:       +33 - (0)6 85 62 59 98
Fax :       +33 - (0)9 58 10 27 44

Fax (D):    +49 - (0)3 21 21 25 22 44

email:      Rainer at krugs.de

Skype:      RMkrug


More information about the grass-dev mailing list