Re: [Pharo-project] Unexpected behavior of roundTo:
On Apr 9, 2011, at 9:09 AM, Andres Valloud wrote:
At the end of the day, we still insist on expecting there won't be loss of information just because we wrote a decimal print string for a binary floating point number. One can get offended or irritated all one wants, but the reality of the situation won't change.
I think the real solution to these "problems" is to implement decimal floating point as per IEEE-754/2008. \\
The MPFR lib seems to me (as far as I understand) is inspired by IEEE 754 <SNIP> MPFR is a portable library written in C for arbitrary precision arithmetic on floating-point numbers. It is based on the GNU MP library. It aims to provide a class of floating-point numbers with precise semantics. The main characteristics of MPFR, which make it differ from most arbitrary precision floating-point software tools, are: ⢠the MPFR code is portable, i.e., the result of any operation does not depend on the machine word size mp_bits_per_limb (64 on most current processors); ⢠the precision in bits can be set exactly to any valid value for each variable (including very small precision); ⢠MPFR provides the four rounding modes from the IEEE 754-1985 standard, plus away-from-zero, as well as for basic operations as for other mathematical functions. .... The following five rounding modes are supported: ⢠MPFR_RNDN: round to nearest (roundTiesToEven in IEEE 754-2008), ⢠MPFR_RNDZ: round toward zero (roundTowardZero in IEEE 754-2008), ⢠MPFR_RNDU: round toward plus infinity (roundTowardPositive in IEEE 754-2008), ⢠MPFR_RNDD: round toward minus infinity (roundTowardNegative in IEEE 754-2008), ⢠MPFR_RNDA: round away from zero (experimental). The âround to nearestâ mode works as in the IEEE 754 standard: in case the number to be rounded lies exactly in the middle of two representable numbers, it is rounded to the one with the least significant bit set to zero. For example, the number 2.5, which is represented by (10.1) in binary, is rounded to (10.0)=2 with a precision of two bits, and not to (11.0)=3. This rule avoids the drift phenomenon mentioned by Knuth in volume 2 of The Art of Computer Programming (Section 4.2.2). </SNIP>
Then you can write something like 1.2345 and know for a fact the number represented is *exactly* 1.2345. At least one VisualWorks platform already supports decimal floating point in hardware (IBM's POWER line). C99 extensions exist at least in draft form to extend C so that it supports decimal floating point. IBM has released a GPL library in ANSI C that implements the feature. I am not sure what is the deal with the license and if you can e.g.: interface to it without making your whole Smalltalk GPL.
MPFR is LGPL, so linking that in the VM or using it via FFI is no problem license wise. Marcus -- Marcus Denker -- http://www.marcusdenker.de INRIA Lille -- Nord Europe. Team RMoD.
On 4/9/11 0:28 , Marcus Denker wrote:
On Apr 9, 2011, at 9:09 AM, Andres Valloud wrote:
I think the real solution to these "problems" is to implement decimal floating point as per IEEE-754/2008. \\
The MPFR lib seems to me (as far as I understand) is inspired by IEEE 754
<quote from the docs>
The docs seem to suggest MPRF implements variable precision binary floating point numbers. IEEE-754/2008, as opposed to IEEE-754/1985, also specifies types for base 10 (i.e.: decimal) floating point numbers. In other words, 2.5 wouldn't be represented as (101)_2, but (25)_10. Thus, going back to the original problem that caused this discussion,
2.8011416510246336 roundTo: 0.01
returns
2.8000000000000003
the problem here is that there is no binary floating point number that can represent the number 0.01. The arguments why this is so are the usual (and I just put them here for the sake of completeness): binary floating point numbers represent fractions of the form +/- m * 2^k where m, k are integers such that 0 <= m < M, and e <= k <= K. So let's try to find which values of m and k match for 0.01: 1/100 = m * 2^k Well, m is not zero, so it must be at least 1, and so k must be negative. Set k' = -k and rearrange: 2^k' = 100m Now we invoke the help of the fundamental theorem of arithmetic that says integers can be factored into primes in only one way. On the left we only have 2 as a prime factor. On the right, there is a factor of 5. Therefore, we conclude the above equality is impossible. So, m and k do not exist, and so no binary floating point number is equal to 0.01. To make the story short, you cannot assume lossless operation just because you can see a base 10 print string. If loss of precision is the issue because we only have 2^k' on the left, let's try base 10 instead. In other words, floating point numbers in which the base is 10 represent values of the form +/- m * 10^k where m, k are integers such that 0 <= m < M, and e <= k <= K. So let's try to find which values of m and k match for 0.01: 1/100 = m * 10^k So now we just match the fraction on the left with m=1 and k=-2. Done. Of course, there are values that cannot be represented without loss of precision, but the loss of precision involves only m and k. For example, 67423523487542376543765376234576235726345623472 = m * 10^k when 0 <= m < M and M = 9. There are not enough digits in the mantissa, so the result is going to be 7*10^k for some k. But this issue happens as well with binary floating point numbers when k is positive. Try 67423523487542376543765376234576235726345623472 asFloat truncated Increasing the precision of binary floating point numbers to arbitrary precision help you if you need a bigger mantissa, but a bigger mantissa does not solve the fundamental problem of binary floating point numbers that causes imprecision whenever you use base 10 to write down values.
MPFR is LGPL, so linking that in the VM or using it via FFI is no problem license wise.
I am not convinced that's what you need: http://en.wikipedia.org/wiki/Decimal_floating_point And it looks like Intel wrote a decimal floating point library, too... now I need to check the license on this one as well: http://software.intel.com/en-us/blogs/2008/03/06/intel-decimal-floating-poin... Andres.
participants (2)
-
Andres Valloud -
Marcus Denker