lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Martin Hollis escribió:

> I think the main problem with using floating point as the only numeric
type
> in lua is: most programmers do not understand floating point. After all,
it
> is A LOT more complicated than integer. I think most programmer's mental
> model of floating point is: sometimes the result of an operation is very
> slightly wrong. As a consequence, people get jittery.

> The solution to this problem is education. I think the essential
> integer-backwards-compatible behavior of double floating point should be
> emphasized more in the documentation, the website, the faq, the wiki,
etc.
> This question is often raised on this forum and I'm sure for every vocal
> person with doubts many lurkers are similarly nervous.

I completely agree with this. There are certainly a lot of misconceptions
out there. It's an interesting observation that every valid IEEE 754 bit
sequence (except NaNs and Infinities) exactly represents some number. That
set of numbers is not closed under any of the normal arithmetic operations.
By contrast, with 2's complement representation of integers, all normal
arithmetic operations are closed (except for division by 0) BUT sometimes
the result is wildly incorrect. (And according to the C standard and
contrary to popular belief, unpredictably so, even if many programs do
assume that the results will be in some modulus or other.)

It is also the case that if x, y and z are in the set of numbers exactly
representable in IEEE 754, and x + y == z, then z will be the result of an
IEEE 754 sum of x and y, and similarly for the other arithmetic operations.
(This is also true of 2's complement arithmetic.)

Probably most people's nervousness about floating point arithmetic is
rooted in those desktop calculators in which (10 / 3) * 3 == 9.99999999.
IEEE 754 arithmetic does not do that, in its default configuration (that
is, unless you select an odd rounding mode); it correctly computes 10. (Try
it!) On the other hand, 2's complement arithmetic yields 9 for the same
computation, which is somewhat less accurate. :-)

> If you have a normal modern desktop computer, then you have IEEE 754
> floating point, double precision.

In fact, most likely you have extended precision hidden inside.

> ... snip

> Regarding performance, most serious modern desktop CPUs these days can
> process double floating point as fast as or faster than integer.

Yep. But the key word is "can". I've seen a number of un*x like systems
running on serious modern desktop CPUs with ultrafast floating point units
in which gcc by default uses floating point library calls instead of
compiling in floating point instructions. Go figure.

This is aside from the various critiques out there about how few languages
allow a programmer to actually take advantage of the potentially IEEE 754
compliant hardware; for example, by correctly giving access to the
exception flags, and thereby forcing really slow tests before every
potentially problematic computation. (Or even allowing the use of Infinity
and -Infinity as literals to allow for reasonable guard values.)

> Eg modern
> MIPS, modern PPC, and better. Intel: poor third (too few FP registers).
For
> users of these CPUs the only major remaining potential issues are memory
> bandwidth, memory usage.

Even there, the difference is minimal. In languages which give you access
to more than one length of floating point number, you can store permanent
results in a lower precision if you like. For a properly aligned temporary
result which doesn't fit into the FP registers, the whole value will be
cached at first reference, so the additional cost of the longer value is
negligible. (This is not 100% accurate, since you could squeeze twice as
many temporary integers into a cache line as temporary doubles, but in the
average program, the hit on performance is tiny.)

In any event, VM interpreters like Lua spend far more time decoding
instructions than executing them.

> Am I right in thinking that because of the cell
> size, these considerations are actually irrelevant in lua?

Yes, sort of. In version 4.0, at least -- and I don't think this has
changed in 4.1 -- running on a 32-bit architecture with numbers in double
precision (i.e. the standard x86 configuration), the cell size is 3 full
words (12 bytes); for all values except numbers, at most 8 bytes of this
are actually used. Changing the number type to integer reduces the cell
size to 8 bytes. At first glance, this may seem to be a dramatic
difference, but it will depend on the type of program you're writing and
the precise implementation of malloc. (One standard malloc uses the same
amount of space for 8 and 12 byte objects, for example. As far as I can
see, single-cell mallocs are relatively rare, but it would again depend on
your program style; my programs seem to mostly malloc small tables and
closures. If you happen to be using a malloc which likes to allocate in
powers of two (say, the FreeBSD malloc), you're not going to notice much
difference there: the default table size seems to be 80 bytes with 8-byte
cells and 112 bytes with 12-byte cells, and both of these use up 128 bytes
with the default FreeBSD malloc. The impact on storage is more noticeable
with other mallocs.

The bottom line is that you can always do integer arithmetic with floating
point, but the inverse is harder. It massively complicates language design
to allow both, so in almost all cases (with the exception of integer-only
programs running on embedded systems, for example), double-precision
floating point is the right answer.

This may be frustrating for those who want to do modular arithmetic or play
games with bits. However, tempting though all that is, it is not portable.
(It's amazing the odd bugs you find when you try to run such a program on a
16- or 64-bit architecture.)

R.