Rainer M. Krug wrote:
>> 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
>
> That interface isn't possible. r.mapcalc doesn't have a string type,
> and there's no way that a function's return type can depend upon the
> value of a parameter.
In this case I would suggest different functions, e.g.
round(x) - as it is now
roundI(x, dec) - round to integer, dec>0 is ignored, dec<0 as below
roundD(x, dec) - round to double, where dec is the number of decimals it
should be rounded to
roundF(x, dec) - round to float, where dec is the number of decimals it
should be rounded to
if dec is positive, it is the number of decimals, if negative the
... (no idea what it is called, but if it is -1, 111 is rounded to 110,
-2 111 is rounded to 100)
default from dec would be 0.
These different functions would also have the advantage of probably
being faster then one single function.
1. I wouldn't bother with separate functions, but instead use the type
of the second argument to determine the return type, i.e.
round(x, 1) -> CELL
round(x, 1.0f) -> FCELL
round(x, 1.0) -> DCELL
The value of the second argument can be ignored, or it can be used for
other purposes.
2. Rounding to a given number of decimals is unnecessarily limiting.
The algorithm for generalised rounding is essentially:
roundTo(x, k) = round(x / k) * k.
Rounding to N decimal places is just a case of using k=1/10^N. If you
allow k to be specified directly, then you can round to arbitrary
steps (e.g. k=5 would round to the nearest multiple of 5, etc).
3. However: there's a slight problem with doing it that way: 0.1 isn't
exactly representable in binary, so e.g. x/0.1 isn't equal to x*10; it
would be more accurate to use:
roundTo(x, k) = round(x * k) / k
where k is the reciprocal of the step, so k=10^N to round to N decimal
places (or k=2 to round to 1/2).
The downside is that the interface is less useful if you want to round
to something other than a fixed number of decimal places. E.g. if you
wanted to round to the nearest multiple of 45 degrees, you'd need to
use k=1.0/45, which isn't exactly representable.
--
Glynn Clements <glynn@gclements.plus.com>