The result of (0).toExponential(1)

# DX Jin (14 years ago)

(0).toExponential(1) should, according to the algorithm in 15.7.4.6, return "0e+0".

But all browser implementations return "0.0e+0" instead.

Which is wrong? The specification or the implementations?

# Jens Nockert (14 years ago)

On H.24/03/08, at 12:39, DX Jin <dox.jin at gmail.com> wrote:

(0).toExponential(1) should, according to the algorithm in 15.7.4.6, return "0e+0".

But all browser implementations return "0.0e+0" instead.

Which is wrong? The specification or the implementations?

Neither, the result is correct. The number is the same, just different representations as strings.

# 程劭非 (14 years ago)

I don't think so.

ES5 specified the algorithm of toExponential. ¡°The number is the same¡± is not the only requirement.

See the algorithm below: ( please pay attention to 8.a )

Let x be this Number value es5.github.com/#this-Number-value. 2.

Let f be ToInteger es5.github.com/#x9.4(fractionDigits). 3.

If x is NaN, return the String "NaN". 4.

Let s be the empty String. 5.

If x < 0, then 1.

  Let *s* be *"-"*.
  2.

  Let *x* = ¨C*x*.
  6.

If x = +¡Þ, then 1.

  Return the concatenation of the Strings *s* and *"Infinity"*.
  7.

If fractionDigits is not undefined and (f < 0 or f > 20), throw a RangeError es5.github.com/#x15.11.6.2 exception. 8.

If x = 0, then 1.

  *Let f = 0.*
  2.

  Let *m* be the String consisting of *f*+1 occurrences of the
  character ¡®0¡¯.
  3.

  Let *e* = 0.
  9.

Else, x ¡Ù 0 1.

  If fractionDigits is not *undefined*, then
  1.

     Let *e* and *n* be integers such that 10*f* ¡Ü *n* < 10*f*+1 and
     for which the exact mathematical value of *n* ¡Á 10*e*¨C*f* ¨C *x* is
     as close to zero as possible. If there are two such sets of *e*
      and *n*, pick the *e* and *n* for which *n* ¡Á 10*e*¨C*f* is larger.
     2.

  Else, *fractionDigits* is *undefined*
  1.

     Let *e*, *n*, and *f* be integers such that *f* ¡Ý 0, 10*f* ¡Ü *n* <
     10*f*+1, the number value for n¡Á 10*e*¨C*f* is *x*, and *f* is as
     small as possible. Note that the decimal representation of*n* has *
     f*+1 digits, *n* is not divisible by 10, and the least significant
     digit of *n* is not necessarily uniquely determined by these
     criteria.
     3.

  Let *m* be the String consisting of the digits of the decimal
  representation of *n* (in order, with no leading zeroes).
  10.

If f ¡Ù 0, then 1.

  Let *a* be the first character of *m*, and let *b* be the remaining *f
  * characters of *m*.
  2.

  Let *m* be the concatenation of the three Strings *a*, *"."*, and *b*.
  11.

If e = 0, then 1.

  Let *c* = *"+".*
  2.

  Let *d* = *"0".*
  12.

Else 1.

  If *e* > 0, then let *c* = *"+".*
  2.

  Else, *e* ¡Ü 0
  1.

     Let *c* = *"-"*.
     2.

     Let *e* = ¨C*e*.
     3.

  Let *d* be the String consisting of the digits of the decimal
  representation of *e* (in order, with no leading zeroes).
  13.

Let m be the concatenation of the four Strings m, "e", c, and d . 14.

Return the concatenation of the Strings s and m.

According to this algorithm, (0).toExponential(1) should return "0e+0".(f is set to 0)

But it looks none of V8, spidermonkey and JScript did that thing. Their result is "0.0e+0".

So is there anyone could give some message about why does ES5 define this behavior like this? Or is it simply a spec bug?

2012/3/8 Jens Nockert <jens at nockert.se>

# DX Jin (14 years ago)

Later, I saw the ES5 draft history[1], Step 15 in the previous version of the "Sunnyvale"( 23 Feb 2009 ) and step 8.a in the "Sunnyvale"( 02 March 2009 ) are the same intention. Step 15 in the previous version of the "Sunnyvale" is only execute if this number value is 0 and fractionDigits is undefined, But step 8.a in "Sunnyvale" is also execute if fractionDigits is not undefined.

so step 8.a should be "a. if fractionDigits is undefined, then let f = 0.".

[1] es3.1:es3.1_proposal_working_draft

在 2012年3月8日 下午10:34,程劭非 <csf178 at gmail.com>写道:

# Kang-Hao (Kenny) Lu (14 years ago)

(12/03/10 17:33), DX Jin wrote:

Later, I saw the ES5 draft history[1], Step 15 in the previous version of the "Sunnyvale"( 23 Feb 2009 ) and step 8.a in the "Sunnyvale"( 02 March 2009 ) are the same intention. Step 15 in the previous version of the "Sunnyvale" is only execute if this number value is 0 and fractionDigits is undefined,

Namely, Step 15 was skipped as Step 11 says

# If x = 0, go to step16.

But step 8.a in "Sunnyvale" is also execute if fractionDigits is not undefined.

so step 8.a should be "a. if fractionDigits is undefined, then let f = 0.".

This is probably an error introduced by the refactoring of this section which happended in between these versions (23 Feb 2009 - 02 March 2009)