http://www.newton-inc.com/dev/techinfo/qa/qa.htm
Floor
and Ceiling
seem broken. For instance, Floor(12.2900 * 10000)
returns 122899, not 122900. What's going on? Floor
or Ceiling
. This happens because of the way floating point numbers are stored, and the limitation is common to many real number representations. In the same way that 1/3 cannot accurately be represented in a finite number of digits in base 10 (it is .3333333333...), likewise 1/10 cannot be exactly represented as a fractional part in base 2. Because number printers typically round to a small number of significant digits, you don't normally notice this. The NTK inspector, for example, displays only 5 significant figures in floating point numbers. However, if you display the number with enough precision, you'll see the representation error, where the real is actually slightly larger or smaller than the intended value. FormattedNumberStr(0.1, "%.18f") -> "0.100000000000000010"
FormattedNumberStr(0.3, "%.18f") -> "0.299999999999999990"
Floor
and Ceiling
are strict, and do not attempt to take this error into account. In the example, 12.29
is actually 12.2899999999999990
, which multiplied by 10000
is 122,899.999999999990
. The largest integer less than this number (Floor
) is correctly 122899
.RIntToL
, which rounds to the nearest integer avoiding the problems caused with round-off error and Floor
or Ceiling
. RIntToL(x)
produces the same result that Floor(Round(x))
would produce. RIntToL(12.29*10000) -> 122900
FormattedNumberStr
. These functions typically round to the nearest displayable value. To display 2 decimal digits, use "%.2f": FormattedNumberStr(12.29, "%.2f") -> "12.29"
$29.95
as the integer 2995
or 29950
, then divide by 100
or 1000
to display the number. If you do this, keep in mind that there is a maximum representable integer value, 0x1FFFFFFF
or 536870911
, which is sufficient to track over 5 million dollars as pennies, but can't go much over that.Floor
deals with round off errors, you'll need to do some extra work keeping track of the precision of the number and the magnitude of the round off error. It's worthwhile to read a good numeric methods reference. Floating point numbers in NewtonScript are represented by IEEE 64-bit reals, which are accurate to around 15 decimal digits. The function NextAfterD
provides a handy way to see how 'close together' floating point numbers are. FormattedNumberStr(NextAfterD(0.3, kInfinity), "%.18f");
-> "0.300000000000000040"