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
 >>> tw.addwatch('n','_roundquotient', bits) #watch n
 >>> tw.addwatch('leftover','_roundquotient', bits)
 >>> tw.addwatch('c','_roundquotient', bits)
 >>> tw.addwatch('x','_roundquotient', bits)
 >>> tw.addwatch('y','_roundquotient', bits)
 >>> 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



More information about the Python-list mailing list