# Decimal arithmetic, with example code

Bengt Richter bokr at oz.net
Sat Oct 5 07:11:19 CEST 2002

```On 4 Oct 2002 00:51:40 GMT, bokr at oz.net (Bengt Richter) wrote:

>On 3 Oct 2002 18:16:55 GMT, bokr at oz.net (Bengt Richter) wrote:
>
>>On 3 Oct 2002 07:08:38 GMT, bokr at oz.net (Bengt Richter) wrote:
>>[...]
>>>
[...]
>I'm testing a debugging class using sys.settrace, so the above is not getting thorough
>attention, except that I can now look at it with the new tool ;-)

It's called tracewatch.py, and defines a single class TraceWatch
Here's a little log of using it on the unchanged fixedpoint.py:
(I defined a formatting function (bits below) to monitor the variables in binary,
also right-justifying on the next line, so things line up).

>>> from fixedpt.fixedpoint import FixedPoint as F
>>> from tracewatch import TraceWatch as TW
>>> tw = TW()
>>> from miscutil import prb
>>> def bits(x):
...     return '\n%60s' % prb(x)
...
>>> tw.addwatch('_roundquotient','#f', bits) #watch calls and returns
>>> F(1.125)
FixedPoint('1.12', 2)
>>> tw.on()
>>> F(1.125)
--------------------------------------------------------------------
File: "fixedpoint.py"
Line [scope] C:all, R:eturn eX:cept S:tack N:ew M:od E:quiv U:nbound
---- ------- -------------------------------------------------------
447 [_roundquotient]:  C: _roundquotient(x=15099494400L, y=134217728L)
N: y =
1000000000000000000000000000
N: x =
1110000100000000000000000000000000
N: n =
1110000
N: leftover =
100000000000000000000000000
454 [_roundquotient]:
N: c =
0
456 [_roundquotient]:
458 [_roundquotient]:  R: _roundquotient(...) =>
1110000
FixedPoint('1.12', 2)

Doing the same thing, but just monitoring _tento with default output
formatting is interesting because of the exception:

>>> from fixedpt.fixedpoint import FixedPoint as F
>>> from tracewatch import TraceWatch as TW
>>> tw = TW()
>>> tw.addwatch('_tento','#f') # watch calls _tento and returns
>>> tw.on()
>>> F(1.125)
--------------------------------------------------------------------
File: "fixedpoint.py"
Line [scope] C:all, R:eturn eX:cept S:tack N:ew M:od E:quiv U:nbound
---- ------- -------------------------------------------------------
405 [_tento]:          C: _tento(n=2, cache={})
408 [_tento]:          X: KeyError(2)
S: < set_precision:246 < __init__:133 < ?:1
411 [_tento]:          R: _tento(...) => 100L
405 [_tento]:          C: _tento(n=2, cache={2: 100L})
408 [_tento]:          R: _tento(...) => 100L
405 [_tento]:          C: _tento(n=2, cache={2: 100L})
408 [_tento]:          R: _tento(...) => 100L
FixedPoint('1.12', 2)
>>> F(1.125)
405 [_tento]:          C: _tento(n=2, cache={2: 100L})
408 [_tento]:          R: _tento(...) => 100L
405 [_tento]:          C: _tento(n=2, cache={2: 100L})
408 [_tento]:          R: _tento(...) => 100L
405 [_tento]:          C: _tento(n=2, cache={2: 100L})
408 [_tento]:          R: _tento(...) => 100L
FixedPoint('1.12', 2)
>>> F(1.125,3)
405 [_tento]:          C: _tento(n=3, cache={2: 100L})
408 [_tento]:          X: KeyError(3)
S: < set_precision:246 < __init__:133 < ?:1
411 [_tento]:          R: _tento(...) => 1000L
405 [_tento]:          C: _tento(n=3, cache={2: 100L, 3: 1000L})
408 [_tento]:          R: _tento(...) => 1000L
405 [_tento]:          C: _tento(n=3, cache={2: 100L, 3: 1000L})
408 [_tento]:          R: _tento(...) => 1000L
FixedPoint('1.125', 3)
>>> F(1.125,3)
405 [_tento]:          C: _tento(n=3, cache={2: 100L, 3: 1000L})
408 [_tento]:          R: _tento(...) => 1000L
405 [_tento]:          C: _tento(n=3, cache={2: 100L, 3: 1000L})
408 [_tento]:          R: _tento(...) => 1000L
405 [_tento]:          C: _tento(n=3, cache={2: 100L, 3: 1000L})
408 [_tento]:          R: _tento(...) => 1000L
FixedPoint('1.125', 3)
>>> tw.show()
-------------------------------------------------------------
B: watch Binding F: watch Function calls/rets  T: Trace scope
X:                  name  scope                formatter
-- ---------------------  -------------------  --------------
F:               _tento  _tento                repr

It's evolved, but it's not finished evolving. There's only one thing to import,
so it's easy to use. But I am not finished messing with it yet. I want to be
able to monitor instance and class variables, and also *args,**kwargs.
Also redirectable output and simultaneous log with interactive sessions.

As you can see, it monitors a name binding for different kinds of changes:

N:ew - new binding to different-valued object,
M:od - old binding to same but modified object
E:quiv - new binding to new object of equivalent value
U:nbound - no binding at all

>>> from tracewatch import TraceWatch as TW
>>> tw = TW()
>>> tw.addwatch('m','?') # m in the interactive scope
>>> tw.on()
>>> if 1:
...     m=1
...     m+=1
...     m = [1]
...     m += [2]
...     m = [1, 2]
...     del m
...
--------------------------------------------------------------------
File: "<stdin>"
Line [scope] C:all, R:eturn eX:cept S:tack N:ew M:od E:quiv U:nbound
---- ------- -------------------------------------------------------
N: m = 1
3 [?]:
N: m = 2
4 [?]:
N: m = [1]
5 [?]:
M: m = [1, 2]
6 [?]:
E: m = [1, 2]
7 [?]:
U: m = Unbound
7 [?]:
>>> m=99
This is a new binding
N: m = 99
1 [?]:
>>> m=99
>>> m=99
>>> m=99
but this is the identical 99, so no trigger
>>> m=100
N: m = 100
1 [?]:
>>> m=100
E: m = 100
the "E" says it's new but Equivalent, so we know where the magic set ends for 2.2 ;-)
1 [?]:
>>> m=100
E: m = 100
1 [?]:

Regards,
Bengt Richter

```