math::exact(n)
π math::exact(n) β bestie, we're doing EXACT math π
okay so this is a page from the Tcl Math Library (yes, the whole library, not just one lil module) and it's about the math::exact package. sit down, grab a boba, we're gonna learn exact real arithmetic and honestly? it's giving main character energy. π§β¨
πΈ NAME πΈ
math::exact β Exact Real Arithmetic
like... exact exact. not "close enough" exact. EXACT. π
β¨ SYNOPSIS β¨
package require Tcl 8.6 9
package require grammar::aycock 1.0
package require math::exact 1.0.2
::math::exact::exactexpr expr
number ref
number unref
number asPrint precision
number asFloat precision
π¦ DESCRIPTION π¦
so the exactexpr command inside the math::exact package lets you do exact computations over the computable real numbers. and bestie, listen β these are not arbitrary-precision calculations. that's a different thing. these are exact, no cap. the numbers get represented by algorithms that just keep producing successive approximations, forever, like a girl who keeps sending "one more thing" texts. π
at the end of a calculation you, the caller, can request a given precision for the final result β and all the intermediate results get computed to whatever precision is necessary to satisfy that request. it's adaptive. it's smart. it's iconic. periodt. π
π PROCEDURES π
this is the main event, the procedure that gets you in the door:
::math::exact::exactexpr exprβ takes a mathematical expression written in Tcl syntax, and hands you back an object representing the program that will calculate successive approximations of that expression's value. we're gonna call the thing it returns an exact real number. π«Άnumber refβ bumps up the reference count of a given exact real number. (yes bestie, you have to do this. keep reading.)number unrefβ brings the reference count back down, and destroys the number if the reference count hits zero. bye babe π«‘number asPrint precisionβ formats the number for printing at the precision you asked for. (how precision actually gets interpreted? there's a whole section, keep scrolling π ) numbers that are known to be rational get formatted as fractions. cute.number asFloat precisionβ also formats the number for printing at the specified precision, same precision rules. but this one formats all numbers in floating-pointEformat. no fractions here, we're going full floatie. π
π PARAMETERS π
exprβ the expression to evaluate. the syntax is the same as Tcl's syntax, BUT the set of operations is smaller. (see Expressions down below for the deets π)numberβ the object that an earlier call tomath::exact::exactexprgave you.precisionβ the requested 'precision' of the result. and okay so this is the part that lowkey trips people up, so let's be real precise about precision: it's (approximately) the absolute value of the binary exponent plus the number of bits of the binary significand. fr fr.
so like, to return results at IEEE-754 double precision, you need 56 bits plus the exponent. let's break that down:
- numbers between
1/2and2β need a precision of57 - numbers between
1/4and1/2, or between2and4β need58 - numbers between
1/8and1/4, or between4and8β need59 - and so on and so on and so on βΎοΈ
π EXPRESSIONS π
the math::exact::exactexpr command accepts expressions from a subset of Tcl's syntax. here's everything you're allowed to use in an expression:
- Decimal integers. π’
- Variable references with the dollar sign (
$). the variable's value has to be the result of another call tomath::exact::exactexpr. and heads up: the reference count of that value gets increased by one for each position where it shows up in the expression. every. single. position. π - The exponentiation operator (
**). - Unary plus (
+) and minus (-) operators. - Multiplication (
*) and division (/) operators. - Parentheses used for grouping.
- Functions. (see Functions right below for the whole list π«Ά)
π₯ FUNCTIONS π₯
here's every function you can use inside an exact real expression. no more, no less, don't try to sneak anything in bestie:
acos(x)β the inverse cosine of x. result comes out in radians. the absolute value of x must be less than 1.acosh(x)β the inverse hyperbolic cosine of x. x must be greater than 1.asin(x)β the inverse sine of x. result is in radians. absolute value of x must be less than 1.asinh(x)β the inverse hyperbolic sine of x.atan(x)β the inverse tangent of x. result is in radians.atanh(x)β the inverse hyperbolic tangent of x. the absolute value of x must be less than 1.cos(x)β the cosine of x. x is expressed in radians.cosh(x)β the hyperbolic cosine of x.e()β the base of the natural logarithms =2.71828...exp(x)β the exponential function of x.log(x)β the natural logarithm of x. x must be positive.pi()β the value of pi =3.15159...(yes, that's what the page says, we don't editorialize π)sin(x)β the sine of x. x is expressed in radians.sinh(x)β the hyperbolic sine of x.sqrt(x)β the square root of x. x must be positive.tan(x)β the tangent of x. x is expressed in radians.tanh(x)β the hyperbolic tangent of x.
β SUMMARY β
so the math::exact::exactexpr command gives you a whole system for doing exact arithmetic over computable real numbers, where the numbers are literally algorithms for successive approximation. π€―
here's the vibe β an example that implements the high-school quadratic formula:
namespace import math::exact::exactexpr
proc exactquad {a b c} {
set d [[exactexpr {sqrt($b*$b - 4*$a*$c)}] ref]
set r0 [[exactexpr {(-$b - $d) / (2 * $a)}] ref]
set r1 [[exactexpr {(-$b + $d) / (2 * $a)}] ref]
$d unref
return [list $r0 $r1]
}
set a [[exactexpr 1] ref]
set b [[exactexpr 200] ref]
set c [[exactexpr {(-3/2) * 10**-12}] ref]
lassign [exactquad $a $b $c] r0 r1
$a unref; $b unref; $c unref
puts [list [$r0 asFloat 70] [$r1 asFloat 110]]
$r0 unref; $r1 unref
and the program prints this result:
-2.000000000000000075e2 7.499999999999999719e-15
now here's the tea π΅ β if IEEE-754 floating point had been used instead, a catastrophic roundoff error would have yielded a smaller root that is a factor of two too high:
-200.0 1.4210854715202004e-14
the exactexpr invocations should be pretty self-explanatory. the other commands of note are ref and unref. and bestie, this part is IMPORTANT: it's on you, the caller, to keep track of references to exact expressions β you call ref every single time an exact expression gets stored in a variable, and you call unref every time that variable goes out of scope or gets overwritten. no cap, if you slack on this you will have a bad time. π
and the asFloat method emits decimal digits for as long as the requested precision supports them. it terminates when the requested precision yields an uncertainty of more than one unit in the least significant digit. so it knows when to stop. queen behavior. π
π CATEGORY π
Mathematics
π COPYRIGHT π
Copyright (c) 2015 Kevin B. Kenny <kennykb@acm.org>
Redistribution permitted under the terms of the Open Publication License <http://www.opencontent.org/openpub/>
okay that's the whole page, no skips, no cuts, every single flag and function accounted for. you're welcome. π«Ά
and a lil sign-off from me to you: this beauty comes from tcllib, version 1.0.2, and it's the math::exact(n) page. go do exact math, bestie. slay. π
β¨πΈ
π¦ where this page comes from
- fedora 43: tcllib 2.0-3.fc43 Β· TCL
- fedora 44: tcllib 2.0-4.fc44 Β· TCL
- nixos 26.05: tcllib 2.0
- nixpkgs unstable: tcllib 2.0
- Copyright (c) 2015 Kevin B\&. Kenny <kennykb@acm\&.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms