ES Decimal status

Mike Cowlishaw MFC at uk.ibm.com
Thu Sep 25 07:24:57 PDT 2008


[Was on airplanes since my last post, arrived late in SeaTac ... will try 
and consoliate replies on this thread to one e-mail :-)]


> >> I'm not sure what you are getting at. a[1] and a[1.000] refer to the
> >> same property in ECMAScript, but a[1m] and a[1.000m] would not. Are
> >> you saying this isn't a problem?
> >
> > Absolutely not a problem ... many languages (and ES itself) which 
> > index
> > 'arrays' by strings treat the index "1.000" as different from "1", and
> > this is not considered a problem.
> 
> But they do not treat 1.000 as an index differently from 1. Explicit 
> string indexes, whether literally expressed or computed, are not the 
> issue here.
[and later:]
> I should have written "explicitly string-typed indexes", or perhaps 
> "intentionally string-type indexes".
> 
> So far, intentions aside, people writing JS can and arguably do count 
> on any integer result of an index computation being equivalent to 
> that index expressed literally as the === integer constant with no 
> trailing zeroes after the decimal point.
> 
> This a === b => o[a] is o[b] invariant (ignore the tiny number 
> exceptions; I agree they're undesirable spec bugs) is what folks on 
> the list are concerned about breaking, for integral values. 
> Fractional index values and strings consisting of numeric literals 
> with and without trailing zeroes are different use-cases, not of 
> concern.

OK, and also liorean says:
> I'm of the opinion that decimal128 and binary64 should behave 
identically in as many areas as possible.

That's a valid model.  I suppose I see strings and decimals as being 
'closer' in concept, and in both "what you see is what you get".  But for 
arrays, I see the problem.  In that case 'reduce to shortest form, that is 
strip trailing zeros, might be the right thing to do for decimals used as 
array indices.  That function is in Sam's implementation (it's called 
'reduce').

> > This is, no doubt, because if one is treating array indexes as a 
> > set of
> > integers you use integer operations on those indexes (almost 
> > exclusively
> > +, -, and *).  If one does use a divide,
> 
> Maciej pointed out reciprocal multiplication as strength-reduced 
> division; this is done often enough in graphics and other low-level 
> code.

Hmm, his example was dividing an integer by 2.  Why would one multiply by 
0.5 for that when the compiler would convert to a shift?

> > it would be carefully chosen to produce an integer result;
> 
> But what if scale is preserved?

My use of terminology without defining it was sloppy, sorry.  In the 
decimal context, I mean by 'integer' a decimal float whose exponent is 0. 
(That is, the significand is the integer.)  With the unnormalized decimal 
float representation, that set of floats *is* the decimal integer 'type' 
(a separate integer type, binary or decimal, is unnecessary).   Hence the 
scale being preserved is 0, which is what one wants.

> > anything which produced a result without an
> > exponent of 0 would always be more likely to give a non-zero 
> > fraction that
> > .0, .00, .000, etc. -- and those non-zero ones would fail rapidly.
> 
> Sorry, I didn't follow this ("that" should be "than"?).

Yes, 'than'.  Was trying to answer in a 20-minute slot at airport -- I 
should have waited ...

- - - - -

> > All I can say is that is has never been a problem in languages such as
> > Rexx and EXEC 2 which have had exactly that behaviour for almost 30 
> > years.
> > I do not recall a single problem report about that behavior.
> 
> I'm not familiar with Rexx, but my cursory reading of the Wikipedia 
> article on it seems to indicate Rexx does not have arrays, but rather 
> "compound variables" which have a different behavior and syntax. It 
> seems to say that stem.1.0 implies simulation of a multidimentional 
> array, not an array index with more precision (and similarly stem. 
> 1.0.0). It also seems that stem..1 would not refer to the same 
> location as stem.0.1 (perhaps it is a syntax error?).

They are essentially string-indexed arrays/vectors.  The syntax is a bit 
odd (square brackets were not available on all keyboards at the time) but 
stem.foo.bar is effectively  stem[foo, bar] where foo and bar are any 
strings (and that syntax is allowed/used in NetRexx).

> I'm sure you know way more about Rexx than I do, but from basic 
> research it seems that its array-like feature does not look or act 
> like ECMAScript arrays, so I am not sure the experience is relevant. I 
> think most people would expect behavior more like C or Java or Perl or 
> Python arrays than like Rexx compound variables.

I think the ES arrays are very similar -- but I agree, when only integer 
values are used, the arrays look like C arrays to many people (more on 
this below in response to another comment).

- - - - -
Waldemar wrote:

> > This is, no doubt, because if one is treating array indexes as a set 
of
> > integers you use integer operations on those indexes (almost 
exclusively
> > +, -, and *).
> 
> Mike;
> 
> The claim that using only integers and only multiplication will save 
array
> indexing is false.  Under your current proposal exactly the same 
problems
> occur even if you use exclusively integers.  For example,
> 
> a[10m*10m*10m*10m*10m*10m]
> 
> and
> 
> a[1e6m]
> 
> refer to different array elements under your proposal.

The problem here was my ill-defined use of 'integer', sorry.  1e+6m is not 
an 'integer' in the sense that I meant (although it has the same value as 
one).  If one uses only values of the form iiiiiim (where i is a digit, 
not dot or 'e'), then multiplying them, adding them, subtracting them, or 
using divideInteger on them will always result in an integer with exponent 
0 -- a value of the same form.  i.e., one can carry out conventional 
'integer arithmetic' safely, and the results will be integers. 
(divideInteger is an explicit integer-divide, but it can also be effected 
by a regular divide and a quantize with appropriate rounding).

The result will also be an 'integer' for regular division of j/k if k is 
an integer and j is a multiple of k (as would be the case when calculating 
array indices).

- - - - -

Brendan summed up:

> Ignoring === as faux eq, the only issue here is d.toString() for decimal 
d: should it preserve scale and stringify trailing zeroes and funny 
exponents?

Are there any other cases like array indices where toString of a number is 
used in a way such that "1.000" is materially different than "1"? 
Certainly toString could reduce, and there could be a differently-spelled 
operation to produce the 'nice' string, but the principle that toString 
shows you exactly what you have got is a good one.  (And it would be 
goodness for ES to behave in the same way as other languages' toString for 
decimals, too.)

In particular, when dealing with currency values, the number of decimal 
places does correspond to the quantum (e.g., whether the value is cents, 
mils, etc., and similarly for positive exponents, it indicates that one is 
dealing in (say) $millions). 

If the 'business logic' calculates a value rounded to the nearest cent 
then the default toString will display that correctly without any 
formatting being necessary (and if formatting were applied then if the 
business logic were later changed to round to three places, the display 
logic would still round to two places and hence give an incorrect result). 
 In short: the act of converting to a string, for display, inclusion in a 
web page, etc., should not obscure the underlying data.  If there's some 
path in the logic that forgot to quantize, for example, one wants to see 
that ASAP, not have it hidden by display formatting.

Mike
























Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 
741598. 
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU








More information about the Es-discuss mailing list