Hi Nocolas,

Thanks for the review.  I have not actually used this for arithmetic yet, I added that in a couple of hours before publishing this.  Previously this has been used to represent the decimal values that I needed to use to load into a database using a fixed length representation.  This need influenced my design quite a bit.  However, without arithmetic, it isn't very useful for many other people (or myself going forward).

As to your points;


(-53/10 asFixedDecimal: 2) fractionPart.

Right.  I  did not finish adding in all of the protocol that should be added.  I will  continue to do this over the next few days as I have time.  For now, this works:

(-53/10 asFixedDecimal: 2) fractionPart. - 0.30

- why maintaining so many forms in parallel ?
   Not bug-proof, you happen to update one form not the other...
   sign is not handled in part1 nor part2

This is a result of  what I was originally using it for, which works pretty well (until I introduce bugs, that is).  Keeping the various different forms there does make certain transformations much easier to handle.  However, I might take a look at other ways to handle this.  (Also, this repository is open, is if anyone wants to add a different representation, they are free to do so).

- negated should create a new instance
   rather than modifying the number in place

Yes, that was a bad choice.  It is now making a new instance.

- FixedDecimals does not implement hash,
   therefore cannot be stored in a Dictionary.
   Particularly, cannot be stored in a workspace variable.
   I suggest hash ^self asFraction hash

This is now fixed, as you suggested.  Although I may tweak this (is there a good hash tester available for Squeak?)

- likewise, implement all subclassResponsibility

Right.  I'm working on that...  

        ( 5/3) * (5/3 asFixedDecimal: 2).
        ( 2.0s1) * (5/3 asFixedDecimal: 2).
        (5/3 asFixedDecimal: 2) reciprocal.

Fixed.  See below.

- coercion depends on receiver:
        | a b |
        a := (53/10 asFixedDecimal: 2).
        b := 5.3.
        { (a+b) class.
        (b+a) class. } "is {FixedDecimal . Float}"

Hmmm.  Yes.  I think I want all arithmetic with FixedDecimals to return a FixedDecimal.  Looking as ScaledDecimals, I notice that what is returned is consistent with for a given other magnitude, but not always the same.  Is there a rational behind which type of number is returned?  Is it spelled out in ANSI?
(Also, while checking this, I noticed that .333 does not give you 0.333 but rather 333.  I wonder if I've coded in a bug like that somewhere else?  If the . is the first part of the method or workspace, it just quitely eats it.)

- maybe add another rounding mode in arithmetic (to nearest even...)

I might add something like that as time permits.  Do you have a use for it?

- create a specific notation for transparent read/write, like 5.30f
  (requires some easy support in Number class>>readFrom: or NumberParser)

Will do.

From algebraic point of view, the main concern is that some numbers
might not have any reciprocal...
Unless the reciprocal is a Fraction, and arithmetic op coerce to Fraction...
But, eh, this is just the case of Float:
| f |
f := (8872240531573379/9007199254740992) asFloat.
f * f reciprocal - 1

Well, this particular number DOES have a reciprocal in FixedDecimals which just happens to be a FixedDecimal.  You just have to specify the scale right:
fd _ (8872240531573379/9007199254740992) asFixedDecimal: 53
rfd _ fd reciprocal
rfd reciprocal
fd * rfd - 1 = 0.00000000000000000000000000000000000000000000000000000
That said, there might be some rational numbers that will not have a reciprocal, but I can't find them.  For instance:
fd _ (1/3) asFixedDecimal: 5  "= 0.33333"
rfd _ fd reciprocal  "= 3.00003"
fd * rfd - 1  "0.00000"

Most of this is now out in SqueakSource.  I'll do some more as time permits.  (Also, all of these changes now have tests, too).

Thanks,
Chris