Softanza
StartFrançais
Softanza
Reference · stzNumber

IsExact()

Numeric surprise is almost always about a frame the caller could not see: a rounding, a binary-float representation, a division that does not terminate. So the number carries that fact rather than making you deduce it -- the same habit as the natural layer's evidential register.

also: is it exact was anything lost is this precise

Basic examples (2)

Softanza
oT = StzNumberQ("1")
oT.Divide("3")
? oT.Content()
? oT.IsExact()
? oT.WhyNotExact()
Output
0.333333
0
the division does not terminate in 6 decimal place(s)

run on 2026-10-02 04:25 inside the library at commit 0e72e2e2c; taken from 07-a-number-that-says-why.en.md(opens in a new tab)

Softanza
oM = StzNumberQ("0.1")
oM.MultiplyBy("3")
? oM.Content()
? oM.IsExact()
? 0.1 * 3 = 0.3
Output
0.3
1
0

run on 2026-10-02 04:25 inside the library at commit 0e72e2e2c; taken from 07-a-number-that-says-why.en.md(opens in a new tab)

Scope (8)

Softanza
oS = StzNumberQ("0.1")
oS.Add("0.2")
? oS.Content()
? oS.IsExact()
? oS.Representation()
Output
0.3
1
decimal

run on 2026-10-02 04:25 inside the library at commit 0e72e2e2c; taken from 07-a-number-that-says-why.en.md(opens in a new tab)

Softanza
oQ = StzNumberQ("1/3")
? oQ.Representation()
? oQ.IsExact()
oQ.Add("2/3")
? oQ.Content()
? oQ.Same(1)
Output
rational
1
1
1

run on 2026-10-02 04:25 inside the library at commit 0e72e2e2c; taken from 07-a-number-that-says-why.en.md(opens in a new tab)

Softanza
oMix = new stzNumber("1/4")
oMix.Add("0.25")
# a quarter plus 0.25 is a half
? oMix.Content()
# ...as a fraction, not 0.5
? oMix.Representation()
# ...and exactly
? oMix.IsExact()
# ...which is what lets a third survive meeting a decimal
? (new stzNumber("1/3")).AddQ("0.5").Content()
Output
1/2
rational
1
5/6

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_rationals_narrated.ring(opens in a new tab)

Softanza
tiny = number("1e-20")
oTiny = new stzNumber(tiny)
# the digits are kept
? oTiny.Content()
# ...so the value is still positive
? oTiny.NumericValue() > 0
# ...and scaling it back recovers 1
? oTiny.NumericValue() * number("1e20")
oTiny.MultiplyBy(2)
# it is exact, because the content is a plain decimal the exact path can use
? oTiny.Content()
# ...and says so
? oTiny.IsExact()
Output
0.00000000000000000001
1
1
0.00000000000000000002
1

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_no_loss_narrated.ring(opens in a new tab)

Softanza
oBig = new stzNumber("1/99999999999999999999999999999999")
# a 32-digit denominator survives construction
? oBig.Content()
# ...and reports as a fraction
? oBig.Representation()
oSum = new stzNumber("1/99999999999999999999999999999999")
oSum.Add("1/99999999999999999999999999999999")
# adding it to itself doubles the numerator
? oSum.Content()
# ...exactly
? oSum.IsExact()
# a fraction that reduces from big parts still lands on the small answer
? (new stzNumber("123456789012345678901234567890/246913578024691357802469135780")).Content()
Output
1/99999999999999999999999999999999
rational
2/99999999999999999999999999999999
1
1/2

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_rationals_narrated.ring(opens in a new tab)

Softanza
# 1 / 8 is 0.125
? (new stzNumber("1")).DivideQ("8").Content()
# 0.1 / 4 is 0.025
? (new stzNumber("0.1")).DivideQ("4").Content()
# 10 / 4 is 2.5
? (new stzNumber("10")).DivideQ("4").Content()
# 22 / 5 is 4.4
? (new stzNumber("22")).DivideQ("5").Content()
oThird = new stzNumber("1")
oThird.Divide("3")
# 1 / 3 does NOT claim to be exact
? oThird.IsExact()
# ...and says why
? StzFindFirst("does not terminate", oThird.Why()) > 0
Output
0.125
0.025
2.5
4.4
0
1

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_exactness_narrated.ring(opens in a new tab)

Softanza
# an exact product knows it
? (new stzNumber("19.99")).MultiplyByQ("0.15").IsExact()
# ...with nothing to explain
? (new stzNumber("19.99")).MultiplyByQ("0.15").Why()
# a big-integer sum knows it
? (new stzNumber("9007199254740992")).AddQ(1).IsExact()
oSqrt = new stzNumber("2")
oSqrt.SquareRoot()
# a square root does not pretend
? oSqrt.IsExact()
# ...and names the reason
? StzFindFirst("no exact decimal result", oSqrt.Why()) > 0
# IsApproximate is its mirror
? oSqrt.IsApproximate()
# Exactness() reports the register
? oSqrt.Exactness()
Output
1

1
0
1
1
inexact

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_exactness_narrated.ring(opens in a new tab)

Softanza
oThird = new stzNumber("1/3")
oThird.Add("2/3")
# a third plus two thirds is ONE
? oThird.Content()
# ...exactly
? oThird.IsExact()
# ...and equals the number 1
? oThird.Same(1)
# a third plus a sixth
? (new stzNumber("1/3")).AddQ("1/6").Content()
# a half less a third
? (new stzNumber("1/2")).SubtractQ("1/3").Content()
# two thirds of three quarters
? (new stzNumber("2/3")).MultiplyByQ("3/4").Content()
# a half divided by a quarter is two
? (new stzNumber("1/2")).DivideQ("1/4").Content()
# every one of those is exact
? (new stzNumber("2/3")).MultiplyByQ("3/4").IsExact()
# a third times three is one
? (new stzNumber("1/3")).MultiplyByQ(3).Content()
# ...and adding zero changes nothing
? (new stzNumber("1/3")).AddQ(0).Content()
Output
1
1
1
1/2
1/6
1/2
2
1
1
1/3

run on 2026-10-02 04:23 inside the library at commit 0e72e2e2c; taken from numeric_rationals_narrated.ring(opens in a new tab)

The extensions of this method

Each extension, and whether it exists for this method; an extension that exists combines with the others (FindSTCS).

Extension
Exists
What it adds · The names
Q
no
does what the method does, then returns the object, so the call can be chained
QQ
no
chains on the next, more specific type of object (the Q ladder)
QQQ
no
chains on the most specific type of object (the Q ladder)
QRT
no
returns the result as an object of the requested type
CS
no
takes a case-sensitivity flag
ST
no
takes the position to start from (StartingAt)
IB
no
takes bounds that are included (IncludingBounds)
XT
no
the extended form: more parameters than the base method
XTT
no
yet another extension: a further extended form, after XT
Z
no
includes the position in what it returns
ZZ
no
returns positions as sections, [start, end]
W
no
selects by a condition
WF
no
selects by a condition, with the expressive keywords (@NextItem, @PreviousItem...)
D
no
takes a direction, forward or backward (Directional)
F
no
takes a function (the condition or the update is given as a function); the forms document also uses F for the future form, which defers the action
Many
no
works on a collection of items instead of one (the plural form)
Except
no
takes exceptions, what to leave out (the exceptional form)
U
no
returns the result without duplication

Every example is a test file of the library, run inside the library for this page; only those whose output kept every promise their file wrote are shown.

See also