|(require math/bigfloat)||package: math-lib|
A C type of arbitrary-precision floating-point numbers.
Elementary and special functions that are efficient and proved correct.
Well-defined semantics that correspond with the latest IEEE 754 standard.
With a few noted exceptions, bigfloat functions regard their arguments as if they were exact, regardless of their precision. Conceptually, they compute exact results using infinitely many bits, and return results with (bf-precision) bits by rounding them using (bf-rounding-mode). In practice, they use finite algorithms that have been painstakingly proved to be equivalent to that conceptual, infinite process.
MPFR is free and license-compatible with commercial software. It is distributed with Racket for Windows and Mac OS X, is installed on most Linux systems, and is easy to install on major Unix-like platforms.
Set the bigfloat function result precision using (bf-precision <some-number-of-bits>).
Use bf to convert real values and well-formed strings to bigfloats.
For examples, continue through the FAQ.
Why use math/bigfloat?
There are a few reasons.
Reason: Flonums have either too much or too little precision for your application.
> (flsqrt 3.0)
> (bf-precision 16) > (bfsqrt (bf 3))
> (bf-precision 179) > pi.bf
A flonum has a 53-bit significand (we’ll say it has 53 bits of precision) and an 11-bit exponent. A bigfloat has an arbitrary precision of at least 2 bits and a 31-bit exponent.
Reason: To compute ridiculously large or small numbers with confidence.
Reason: To verify your floating-point hardware.
IEEE 754-2008 stipulates that conforming implementations must correctly round the results of all operations. Roughly speaking, results can’t be more than half a bit off, where the bit in question is the least significant in the significand.
Reason: To control rounding of the least significant bit.
IEEE 754 provides for different rounding modes for the smallest bit of a flonum result, such as round to even and round toward zero. We might use this to implement interval arithmetic correctly, by rounding lower bounds downward and upper bounds upward. But there isn’t a portable way to set the rounding mode!
When shouldn’t I use math/bigfloat?
When you need raw speed. Bigfloat functions can be hundreds to thousands of times slower than flonum functions.
That’s not to say that they’re inefficient. For example, bflog implements the algorithm with the best known asymptotic complexity. It just doesn’t run directly on hardware, and it can’t take fixed-precision-only shortcuts.
Why are there junk digits on the end of (bf 1.1)?
Why is the last digit of pi.bf not rounded correctly?
All the bits but the last is exact, and the last bit is correctly rounded. This doesn’t guarantee that the last digit will be.
A decimal digit represents at most log(10)/log(2) ≈ 3.3 bits. This is an irrational number, so the decimal/bit boundary never lines up except at the decimal point. Thus, the last decimal digit of any bigfloat must represent fewer than 3.3 bits, so it’s wrong more often than not. But it’s the last bit that counts.
> (bf-precision 128) > (bf 4)
> (bf 1/7)
> (bf 41/10)
> (bf "not a number")
bf: expected a well-formed decimal number; given "not a number"
> (bf "15e200000000")
In the last example, the result of (bf "15e200000000") is displayed as a string conversion because the exact rational number would be very large.
* It can be a good idea if you’re testing a flonum implementation of a function against a bigfloat implementation.
> (require (only-in math/base random-bits)) > (bf-precision 64) > (bf (random-bits 64) -64)
> (bf-precision 64)
> (bfcopy (parameterize ([bf-precision (+ (bf-precision) 10)]) (bf/ (bf+ 1.bf (bfsqrt 5.bf)) 2.bf)))
To access the significand and exponent at the same time, use bigfloat->sig+exp.
If (values sig exp) = (bigfloat->sig+exp x), its value as an exact rational is (* sig (expt 2 exp)). In fact, bigfloat->rational converts bigfloats to rationals in exactly this way, after ensuring that (bfrational? x) is #t.
This function and the two-argument variant of bf are mutual inverses.
bigfloat->integer, bigfloat->rational and bigfloat->real return values that can be converted exactly back to x using bf. For the first two, this is done by raising an error if x is not respectively integer or rational. On the other hand, bigfloat->real returns +inf.0, -inf.0 or +nan.0 when x is not a rational bigfloat.
> (bf-precision 64) > (bigfloat->integer (bf 21/10))
bigfloat->integer: contract violation
given: (bf #e2.09999999999999999991)
> (bigfloat->integer (bfround (bf 21/10)))
> (define x (bf 1/7)) > (bigfloat->flonum x)
> (bigfloat->rational x)
> (rationalize (bigfloat->rational x) (expt 2 (- (bf-precision))))
> (bf= x (bf (bigfloat->rational x)))
Be careful with exact conversions. Bigfloats with large exponents may not fit in memory as integers or exact rationals. Worse, they might fit, but have all your RAM and swap space for lunch.
> (bf-precision 64) > (bigfloat->string (bf 4))
> (bigfloat->string (bf 1/10000))
> (string->bigfloat "0.14285714285714285714")
> (string->bigfloat "square root of two")
> (string->bigfloat (bigfloat->string pi.bf))
For nonzero, rational bigfloats, the number of bits bits includes the leading one bit. For example, to simulate 64-bit floating point, use (bf-precision 53) even though flonums have a 52-bit significand, because the one bit is implicit in a flonum.
(bf-rounding-mode mode) → void? mode : (U 'nearest 'zero 'up 'down)
Most bigfloat “constants” are actually identifier macros that expand to the application of a zero-argument function. This allows, for example, pi.bf to depend on the current value of bf-precision, and allows all of them to be constructed lazily. Most constants are memoized, possibly at multiple precisions.
> (bf-precision 10) > pi.bf
> (bf-precision 179) > pi.bf
A “j” in the name indicates that a function computes a Bessel function of the first kind. A “y” indicates the second kind.
The “j” or “y” is followed by the order: zero, one, or n (user-specified).
Two nonzero, rational bigfloats are equal? if and only if their canonicalized significands and exponents are equal. Two zero or non-rational bigfloats are equal? if and only if their canonicalizations are eq?.
Canonicalizing bigfloats won’t change answers computed from them.