Hi.
I've just release a package FixedDecimal on SqueakSource. A FixedDecimal is similar to a ScaledDecimal, but different in certain select ways. It's primary purpose was to be able to represent precise decimals for such things as representing money - where ScaledDecimals leave something to be desired. For instance, with ScaledDecimals, you get: (33.333s withScale:2) + (33.333s withScale:2) print it yields 66.67s but with FixedDecimals, you would get: (33.333 asFixedDecimal: 2) + (33.333 asFixedDecimal: 2) print it yields 66.66. So, FixedDecimals round the numbers to the exact scale you specify - converting a float to a FixedDecimal and back will not necessarily return the starting number, unlike ScaledDecimals. Most simple arithmetic is defined for FixedDecimals, but not all methods that probably should be (it's getting late and I'm going away for the weekend - thought I'd publish what I have). Thanks, Chris |
nice.
On 8/31/07, Chris Cunningham <[hidden email]> wrote: > Hi. > > I've just release a package FixedDecimal on SqueakSource. > > A FixedDecimal is similar to a ScaledDecimal, but different in certain > select ways. It's primary purpose was to be able to represent precise > decimals for such things as representing money - where ScaledDecimals leave > something to be desired. For instance, with ScaledDecimals, you get: > (33.333s withScale:2) + (33.333s withScale:2) print it yields 66.67s > but with FixedDecimals, you would get: > (33.333 asFixedDecimal: 2) + (33.333 asFixedDecimal: 2) print it yields > 66.66. > So, FixedDecimals round the numbers to the exact scale you specify - > converting a float to a FixedDecimal and back will not necessarily return > the starting number, unlike ScaledDecimals. > > Most simple arithmetic is defined for FixedDecimals, but not all methods > that probably should be (it's getting late and I'm going away for the > weekend - thought I'd publish what I have). > > Thanks, > Chris > > > > |
In reply to this post by cbc
Interesting, however current version FixedDecimals.cbc.12.mcz is bugged.
example: (-53/10 asFixedDecimal: 2) fractionPart. Some suggestions: - 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 - negated should create a new instance rather than modifying the number in place - 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 - likewise, implement all subclassResponsibility ( 5/3) * (5/3 asFixedDecimal: 2). ( 2.0s1) * (5/3 asFixedDecimal: 2). (5/3 asFixedDecimal: 2) reciprocal. - coercion depends on receiver: | a b | a := (53/10 asFixedDecimal: 2). b := 5.3. { (a+b) class. (b+a) class. } "is {FixedDecimal . Float}" - maybe add another rounding mode in arithmetic (to nearest even...) - create a specific notation for transparent read/write, like 5.30f (requires some easy support in Number class>>readFrom: or NumberParser) 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 Cheers Nicolas Chris Cunningham a écrit : > Hi. > > I've just release a package FixedDecimal on SqueakSource. > > A FixedDecimal is similar to a ScaledDecimal, but different in certain > select ways. It's primary purpose was to be able to represent precise > decimals for such things as representing money - where ScaledDecimals > leave something to be desired. For instance, with ScaledDecimals, you get: > (33.333s withScale:2) + (33.333s withScale:2) print it yields 66.67s > but with FixedDecimals, you would get: > (33.333 asFixedDecimal: 2) + (33.333 asFixedDecimal: 2) print it > yields 66.66. > So, FixedDecimals round the numbers to the exact scale you specify - > converting a float to a FixedDecimal and back will not necessarily > return the starting number, unlike ScaledDecimals. > > Most simple arithmetic is defined for FixedDecimals, but not all methods > that probably should be (it's getting late and I'm going away for the > weekend - thought I'd publish what I have). > > Thanks, > Chris > > > ------------------------------------------------------------------------ > > |
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 ? 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 Yes, that was a bad choice. It is now making a new instance. - FixedDecimals does not implement hash, Particularly, cannot be stored in a workspace variable. 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). Fixed. See below. - coercion depends on receiver: 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 Will do. From algebraic point of view, the main concern is that some numbers 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" Thanks, Chris |
Chris Cunningham a écrit :
> > - 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? > No, but i just wonder if all monetary application will truncate... |
Free forum by Nabble | Edit this page |