# PEP 327: Decimal Data Type

Anton Vredegoor anton at vredegoor.doge.nl
Mon Feb 9 13:43:02 CET 2004

Tim Roberts <timr at probo.com> wrote:

>anton at vredegoor.doge.nl (Anton Vredegoor) wrote:
>>
>>One possible option would be to provide for some kind of random
>>rounding routine for some of the least significant bits of a floating
>>point value.
>
>answer with 15 decimal places, but now you have non-determinism.  The real
>answer, I think, is getting people to understand how much of their
>real-world measurements are garbage.

Yes, but this is not a simple matter. There is some kind of order long
after strict methods become unwieldy. An intelligent rounding scheme
could harness some of this partial order to keep the computations more
accurate over a wider range of manipulations on real world data.

I'm providing some code below to show that there is order beyond
determinism. It's not very helpful in an explicit way, but it should
serve to prove the point for someone wanting to look at it for long
enough and willing to check the code for some exact deterministic
explanation, and being unable to formalize it :-)

Also it's not bad to look at even for those not wanting to
investigate, so it might help to prevent possible tension in this
discussion a bit.

>>The advantage would be that this would also be usable for
>>DSP-like computations that are used in music programming (volume
>>adjustments) or in digital video (image rotation).
>
>Interesting.  I know you were kind of talking off the top of your head, but
>can you tell me what leads you to thinking that some low-order randomness
>would be helpful in those particular applications?

There are high end digital mixers that use some kind of random
rounding to the least significant bits of their sample data in order
to make the sounds "survive" more manipulations before the effect of
the manipulations becomes audible.

In digital video with image rotation there is the problem of
determining where an object exactly is after it is rotated, because
all of its coordinate points have been rounded. A statistic approach
seems to work well here.

On a more cosmic scale the universe seems to use the same trick of
indeterminism, at least according to quantum theory and the Heisenberg
uncertainty principle. Some think that because of that the universe
itself must be a computer simulation :-) I guess I'd better stop here
before someone mentions Douglas Adams ...

>>Maybe we need a DSP-float instead of a decimal data type? Decimals
>>could be used for testing DSP-float implementations.
>
>Can you describe what you mean by DSP-float?  I'm not sure why a DSP should
>treat floats any differently than an ordinary processor.

You are right, a DSP is just like an ordinary processor, except that
it is specialized for digital signal processing operations. I guess I
got a bit carried away by thinking about a datatype that has builtin
random rounding for the least significant bits. For example by using
the Mersenne twisted random generator, it could compute a lot of
rounding bytes at once and just use them up as needed. This way it
would not slow down the computations too much.

Anton

from __future__ import division
from Tkinter import *
from random import random,choice

class Scaler:

def __init__(self, world, viewport):
(a,b,c,d), (e,f,g,h) = world, viewport
xf,yf = self.xf,self.yf = (g-e)/(c-a),(h-f)/(d-b)
wxc,wyc = (a+c)/2, (b+d)/2
vxc,vyc = (e+g)/2, (f+h)/2
self.xc,self.yc = vxc-xf*wxc,vyc-yf*wyc

def scalepoint(self, a, b):
xf,yf,xc,yc = self.xf,self.yf,self.xc,self.yc
return xf*a+xc,yf*b+yc

def scalerect(self, a, b, c, d):
xf,yf,xc,yc = self.xf,self.yf,self.xc,self.yc
return xf*a+xc,yf*b+yc,xf*c+xc,yf*d+yc

class RandomDot:

def __init__(self, master, n):
self.master = master
self.n = n
self.world = (0,0,1,1)
c = self.canvas = Canvas(master, bg = 'black',
width = 380, height = 380)
c.pack(fill = BOTH, expand = YES)
master.bind("<Configure>", self.configure)
master.bind("<Escape>",  lambda
event ='ignored', m=master: m.destroy())
self.canvas.bind("<Button-1>", self.click)
self.colorfuncs = {'red':(min,min),'green':(min,max),
'blue':(max,min), 'white':(max,max)}
self.polling = False

def poll(self):
self.wriggle()
self.master.after(10, self.poll)

def click(self, event):
self.draw()

def configure(self,event):
self.scale = Scaler(self.world, self.getviewport())
self.draw()
if not self.polling:
self.polling = True
self.poll()

def draw(self):
c,sp = self.canvas,self.scale.scalepoint
c.delete('all')
funcs = self.colorfuncs
colors = funcs.keys()
for i in xrange(1000):
color = choice(colors)
a,b = sp(random(), random())
c.create_oval(a,b,a+5,b+5,fill=color,
outline = '')

def wriggle(self):
c,sp = self.canvas,self.scale.scalepoint
funcs = self.colorfuncs
x = choice(c.find_all())
color = c.itemcget(x,"fill")
f1,f2 = funcs[color]
a = f1([random() for i in xrange(self.n)])
b = f2([random() for i in xrange(self.n)])
a,b = sp(a,b)
c.coords(x,a,b,a+5,b+5)

def getviewport(self):
c = self.canvas
return (0, 0, c.winfo_width(),c.winfo_height())

if __name__=='__main__':
root = Tk()
root.title('randomdot')
app = RandomDot(root,3)
root.mainloop()