Math.PI.toString(16) -> 3.243f6a8885a3 and back

S

Scott Sauyet

Benjamin said:
Am 21.06.2010 21:55, schrieb Scott Sauyet:


Yes, it accepts even "1.0e4" "1.0e-3" "1.0e+4" (base 10), "1f.1fp4"
"1f.1fp+2" "1f.1fp-4" (base 16) and so on as exponent stuff, because
Number.prototype.toString "can" produce so such results, at least in
BESEN and even some other engines.

I saw the exponent code, and am not quite sure how that should play
with bases higher than 14 (it gets tricky when you consider that
"1.0e3", base 10, should convert to 1000 but "1.0e3", base 16, should
convert to 1.055419921875. The question is what does "e" represent?

But do you foresee a need for multiple consecutive minus/plus signs?
 
B

Benjamin 'BeRo' Rosseaux

Am 21.06.2010 22:50, schrieb Scott Sauyet:
I saw the exponent code, and am not quite sure how that should play
with bases higher than 14 (it gets tricky when you consider that
"1.0e3", base 10, should convert to 1000 but "1.0e3", base 16, should
convert to 1.055419921875. The question is what does "e" represent?

"e" is the exponent char at least for base 10, which will can generate
at least at "9.8.1 ToString Applied to the Number Type" in the ES5 spec.
At radix larger than 14, the "e" exponent char will ignored, and at
radix larger than 25, the "p" exponent char will ignored.
But do you foresee a need for multiple consecutive minus/plus signs?

And the other with the multiple minus/plus signs is just for to be
foolproof-safe, and can be changed easy, if needed.
 
S

Scott Sauyet

Benjamin said:
Am 21.06.2010 22:50, schrieb Scott Sauyet:

"e" is the exponent char at least for base 10, which will can generate
at least at "9.8.1 ToString Applied to the Number Type" in the ES5 spec.
At radix larger than 14, the "e" exponent char will ignored, and at
radix larger than 25, the "p" exponent char will ignored.

This might be the best approach, but it certainly feels awkward.

In any case, your approach is similar to the one I posted. Yours
iterates forward over the fractional digits, versus mine which went
backwards. It seems to gain the same additional precision over other
approaches that mine does. But it doesn't round badly on 0.fgr, base
36 as mine did. Definitely a nice version. I'm wondering if it will
round badly on other short strings, but I haven't done any serious
tests.

In a separate post, I will detail a slightly different approach I've
been trying which is intended to clean up the likely (although
untested) performance problems in my earlier version and avoid the
rounding errors with shorter strings.
 
S

Scott Sauyet

Scott said:
I look forward to it.  I need to find a little time for my next
approach, but I do have a new idea as well.

I've found a little time finally, and the new approach definitely
seems an improvement, both in the actual results and the likely
performance considerations.

I no longer lazily load the regexes needed, as I have to save some
other values for each base and it made sense just to compute them
together. I keep a list of the powers of each base less than or equal
to 2^53. I still have a separate parseFraction function, but instead
of working digit-by-digit, it calls parseInt on chunks of as many
digits as will fit inside 2^53.

It's not well-tested yet, but I've posted it on my latest test page,
here:

<http://scott.sauyet.com/Javascript/Test/2010-06-21b/>

The PHP source is at

<http://scott.sauyet.com/Javascript/Test/2010-06-21b/index.phps>

Here is the function:

var parseFloat_ss2 = (function() {
var
origPF = parseFloat,
DEPTH = 2,
maxInt = Math.pow(2, 53),
allDigits = "0123456789abcdefghijklmnopqrstuvwxyz",
regexes = [null, null],
powers = [null, null],
parseFraction = function(str, base) {
if (!str) return 0;
var basePowers = powers[base],
max = basePowers[basePowers.length - 1];
total = 0,
denominator = 1,
count = 0;
while (str.length && count < DEPTH) {
var index = Math.min(str.length, basePowers.length - 1);
total += parseInt(str.substring(0, index), base) /
(denominator * basePowers[index]);
str = str.substring(index);
denominator *= max;
count++;
}
return total;
};
(function() {
for (var base = 2; base <=36; base++) {
var digits = allDigits.substring(0, base);
regexes[base]= new RegExp("(^[\\-\\+]?)([" + digits +
"]*)(?:\\.([" + digits + "]*))?$", "i");
powers[base] = [];
var power = 1, i = 0;
while (power <= maxInt) {
powers[base] = power;
power *= base;
i++;
}
}
}());
return function (str, base) {
if (!base || base == 10) return origPF(str);
if ((base < 2) || (base > 36) || (base % 1)) return NaN;
var regex = regexes[base],
match = regex.exec(str);
if (!match) return NaN;
return ((match[1] == "-") ? -1 : 1) * (
(match[2] == "" ? 0 : parseInt(match[2], base)) +
parseFraction(match[3], base)
);
};
}());
 
D

Dr J R Stockton

In comp.lang.javascript message <7550eef3-42f2-4d97-9459-dea2356aa84b@z8
g2000yqz.googlegroups.com>, Mon, 21 Jun 2010 13:50:01, Scott Sauyet
I saw the exponent code, and am not quite sure how that should play
with bases higher than 14 (it gets tricky when you consider that
"1.0e3", base 10, should convert to 1000 but "1.0e3", base 16, should
convert to 1.055419921875. The question is what does "e" represent?

In a browser, a full function parseFloat(String, radix) should accept
the exponent format which, in that browser, toString(radix) gives for
sufficiently large and small Numbers. But it should accept that format
for all finite values, and with the radical point not in the same
position.
 
D

Dr J R Stockton

In comp.lang.javascript message <703e1d78-8204-4c60-b73f-eac7de238028@j4
g2000yqh.googlegroups.com>, Mon, 21 Jun 2010 12:51:53, Scott Sauyet
I don't understand the first part of that. What browser has the
button covering something important?

The button was covered, in part, by the dropped list.
Does the latest version fix the
UI versions you mention?

<http://scott.sauyet.com/Javascript/Test/2010-06-21a/>

Yes. But you set the width to 800px.

I have a 1280*1024 screen which is a little bigger than A4 landscape.
But I like to be able to work with an editor (A5 portrait) on one side
of the screen and material-to-read in A5 portrait on the other side.
That means that my browser is normally set by
<input type=button value=ReSize
onClick="window.resizeTo(640, window.screen.height*0.85)">
in its home page; and, for browsers where resize does not work, that
page has a fixed-width Table between a pair of <hr> so I pull the side
of the window until the lines and table match.

Code which I edit gets a default 72-character line marking; I write a
little shorter so that it fits into my displays, and then of course it
fits News.


In Opera, one can edit the source copy. You page is nearly OK with min-
width 300 px and actual width 640 px ; a slight reduction in margin or
padding would make it OK.

I'm not, of course, saying that you should set 640 px width; just that
with an unspecified width and economy of margins a reader gets more
choice.


Where you have more than one function from a person, I suggest that the
first be numbered "1". My ExactPF us now called BetterPF for two
reasons, one being that it is not invariably exact.
 
S

Scott Sauyet

Dr said:
In comp.lang.javascript message <703e1d78-8204-4c60-b73f-eac7de238028@j4
g2000yqh.googlegroups.com>, Mon, 21 Jun 2010 12:51:53, Scott Sauyet



Yes. But you set the width to 800px.

That was detritus left over from the earlier layout. I've removed it
from the most recent two versions.

Where you have more than one function from a person, I suggest that the
first be numbered "1".

Good idea. I updated the most recent one to do so.

My ExactPF us now called BetterPF for two
reasons, one being that it is not invariably exact.

If and when I make a new version, I will try to remember to change
that.
 
S

Scott Sauyet

Dr said:
In comp.lang.javascript message <7550eef3-42f2-4d97-9459-dea2356aa84b@z8
g2000yqz.googlegroups.com>, Mon, 21 Jun 2010 13:50:01, Scott Sauyet


In a browser, a full function parseFloat(String, radix) should accept
the exponent format which, in that browser, toString(radix) gives for
sufficiently large and small Numbers.  But it should accept that format
for all finite values, and with the radical point not in the same
position.

That probably stakes out the only practical position, assuming that
all browsers when they report in exponent form always use "+" or "-".
But it leaves the strange ambiguity of things like "6.02214179e23",
which is understood by parseFloat as 6.02214179e+23, but our new
version using base 16 could not understand 7.f8618974d08a8e13 as the
same value, since the final three digits would have to be treated as
digits and not as representing multiplication by the 13th power of our
16.

It's not that this is wrong; it seems the only way to resolve the
potential ambiguity. But it is decidedly odd.
 
D

Dr J R Stockton

In comp.lang.javascript message <4ff2b606-26e5-4649-8136-a99411861ea5@w3
1g2000yqb.googlegroups.com>, Wed, 23 Jun 2010 06:33:48, Scott Sauyet
That probably stakes out the only practical position, assuming that
all browsers when they report in exponent form always use "+" or "-".
But it leaves the strange ambiguity of things like "6.02214179e23",
which is understood by parseFloat as 6.02214179e+23, but our new
version using base 16 could not understand 7.f8618974d08a8e13 as the
same value, since the final three digits would have to be treated as
digits and not as representing multiplication by the 13th power of our
16.

It's not that this is wrong; it seems the only way to resolve the
potential ambiguity. But it is decidedly odd.

One needs to test all browsers, or at least several, before making such
comment. There may be error, but I see no ambiguity.

Browser :- 1e50.toString(35) :-
MS IE 8 3.v3ty6r1g4a8(e+32)
Ff 3.0.19 3v3ty6r1g49vrxtsu3y8yqlp7gi2e9jfa
Opera 10.10 3v3ty6r1g48bx586912esj60h8rsjawka
Safari 4.0.5 3v3ty6r1g48bx586912esj60h8rsjawka
Chrome 5.0 3v3ty6r1g48bx586912esj60h8rsjawka

Browser :- 1e-50.toString(35) :-
MS IE 8 9.002luc6eeb5(e-33)
Ff 3.0.19 0.000000000000000000000000000000009002luc6eef
Opera 10.10 1e-50
Safari 4.0.5 0
Chrome 5.0 0.000000000000000000000000000000009002luc6ee ...

IE8's exponents appear to be decimal powers of radix, but that needs
checking.

So the ideal must be to read fixed point AND IR's exponents.
 
S

Scott Sauyet

Dr said:
In comp.lang.javascript message <4ff2b606-26e5-4649-8136-a99411861ea5@w3
1g2000yqb.googlegroups.com>, Wed, 23 Jun 2010 06:33:48, Scott Sauyet




One needs to test all browsers, or at least several, before making such
comment.  There may be error, but I see no ambiguity.

Browser :-              1e50.toString(35) :-
MS IE 8                 3.v3ty6r1g4a8(e+32)
Ff 3.0.19               3v3ty6r1g49vrxtsu3y8yqlp7gi2e9jfa
Opera 10.10             3v3ty6r1g48bx586912esj60h8rsjawka
Safari 4.0.5            3v3ty6r1g48bx586912esj60h8rsjawka
Chrome 5.0              3v3ty6r1g48bx586912esj60h8rsjawka

Browser :-              1e-50.toString(35) :-
MS IE 8                 9.002luc6eeb5(e-33)
Ff 3.0.19               0.000000000000000000000000000000009002luc6eef
Opera 10.10             1e-50
Safari 4.0.5            0
Chrome 5.0              0.000000000000000000000000000000009002luc6ee ...

IE8's exponents appear to be decimal powers of radix, but that needs
checking.

So the ideal must be to read fixed point AND IR's exponents.

I understand that the output of toString() might always be susceptible
to this method, although I haven't checked it thoroughly. But I
wanted to consider Strings that reasonably represent base-n floating
numbers, things like

7.f8618974d08a8e20

The question, perhaps is whether we want our function to recognize
"6.02214179e23" with radix 10 as an approximation to Avogadro's
Number, which is approximately 6.02214179 multiplied by the 23rd power
of 10. It would make sense to do so. The built-in parseFloat does so
in each of the implementations I've tried.

But then what would we get for "7.f8618974d08a8e20", which could be
interpreted as 7.f8618974d08a8 (base 16) time the 20th power of 16, or
as 7.970238295573418 as all the currently published versions in my
test page do.

That's the ambiguity I see. Do we just assume that all inputs using
exponential notation will use "e+" or "e-"? Or do we cover the base
10 version as a special case? Or is there some other option?
 
D

Dr J R Stockton

In comp.lang.javascript message <872a82c8-5cdf-4c9e-ab3b-0e5f70f37962@j4
g2000yqh.googlegroups.com>, Thu, 24 Jun 2010 17:35:01, Scott Sauyet
I understand that the output of toString() might always be susceptible
to this method, although I haven't checked it thoroughly. But I
wanted to consider Strings that reasonably represent base-n floating
numbers, things like

7.f8618974d08a8e20

The question, perhaps is whether we want our function to recognize
"6.02214179e23" with radix 10 as an approximation to Avogadro's
Number, which is approximately 6.02214179 multiplied by the 23rd power
of 10. It would make sense to do so. The built-in parseFloat does so
in each of the implementations I've tried.

ISTM that ECMA 262 9.3.1 requires it to do so.
But then what would we get for "7.f8618974d08a8e20", which could be
interpreted as 7.f8618974d08a8 (base 16) time the 20th power of 16, or
as 7.970238295573418 as all the currently published versions in my
test page do.
That's the ambiguity I see. Do we just assume that all inputs using
exponential notation will use "e+" or "e-"? Or do we cover the base
10 version as a special case? Or is there some other option?

Base 10 should be handled as a general case. It's easier to develop and
test, since our instincts mostly work in Base 10. If there is no base-
10-specific code, base-10 debugging will debug all bases except for
base-specific errors.

Those people who want greater speed for base 10 or other special cases
such as 2^N can add a neat wrapper to deal with those. Those who have
other code, including parseFloat, for such bases can use it to check the
general code.

Those people who want the greatest speed can sacrifice neatness by
merging the wrapper.

Perhaps the best way overall of handling exponent notation for general
bases is to use a specific punctuation character to do for all bases
what e does for base 10. For that, ^ or @ will serve. There should
also be a way of indicating the radix as part of the number string, as
shown by -123.456^78#9 or otherwise.

There also needs to be a clear indication as to whether the exponent is
to be base radix or base 10.

How about 0x12.34^0x56 ?
 
S

Scott Sauyet

Dr said:
In comp.lang.javascript message <872a82c8-5cdf-4c9e-ab3b-0e5f70f37962@j4
g2000yqh.googlegroups.com>, Thu, 24 Jun 2010 17:35:01, Scott Sauyet




ISTM that ECMA 262 9.3.1 requires it to do so.

Yes, but that does not have to constrain our function.

Base 10 should be handled as a general case.  It's easier to develop and
test, since our instincts mostly work in Base 10.  If there is no base-
10-specific code, base-10 debugging will debug all bases except for
base-specific errors.

I'm not sure what you mean by "Base 10 should be handled as a general
case." Obviously, we're talking here about generalizing *from* the
base-10 case.

My function followed Thomas' lead and defaulted to the existing
(base-10) parseFloat function if the radix is not supplied or if the
radix is 10. This of course does treat base-10 as a special case.
There is some obvious justification for that, but there are clear
counter-arguments as well to having any such special cases.
Those people who want greater speed for base 10 or other special cases
such as 2^N can add a neat wrapper to deal with those.  Those who have
other code, including parseFloat, for such bases can use it to check the
general code.

Those people who want the greatest speed can sacrifice neatness by
merging the wrapper.

I'm afraid I don't follow this.
Perhaps the best way overall of handling exponent notation for general
bases is to use a specific punctuation character to do for all bases
what e does for base 10.  For that, ^ or @ will serve.  There should
also be a way of indicating the radix as part of the number string, as
shown by -123.456^78#9 or otherwise.

Uggh!

This seems to be veering sharply away from the original idea of
pairing a version of parseFloat with the existing Number.toString() so
that we can reasonably switch representations, which I understood as
at least part of the goal of your original suggestion that "ECMA 6
should specify a Method whereby for ANY
Number X the result of X.toString(B) can be converted to the original
X ."

This suggestion also has the ugly feature that experience with other
languages could easily make one expect "1.23^45" to represent the
forty-fifth power of 1.23 rather than 1.23 * the forty-fifth power of
ten.

There also needs to be a clear indication as to whether the exponent is
to be base radix or base 10.

How about 0x12.34^0x56 ?

Can you think of a good justification for mixing and matching a
base-10 exponent with a mantissa expressed in a different base? I
can't come up with one. I would suggest that the base be used for all
digits in the String format.

-- Scott
 
D

Dr J R Stockton

In comp.lang.javascript message <4ba0b1f4-f63e-4c44-b87a-20a24b4953a4@q1
2g2000yqj.googlegroups.com>, Mon, 28 Jun 2010 07:34:06, Scott Sauyet
Yes, but that does not have to constrain our function.

Actually, ECMA 262 is wrong. Name "parseFloat" should mean that the
action "parse" is applied to a "Float" - and 123.456e78 is in floating-
point notation but 1234.5678 is in fixed=point notation. The fact that
the result is a floating-point type is grammatically irrelevant. A
better name would be "parseToFloat".

Routines not using exponents such as we have been considering should be
called not "parseFloat" but "parseFixed".

Given a parseFixed, one can make a parseFloat by wrapping it to hdle the
mantissa in with code to handle the exponent (which might also use
parseFixed or part thereof).

The "F" in my routine "BetterPF" has just changed its meaning.


I'm not sure what you mean by "Base 10 should be handled as a general
case." Obviously, we're talking here about generalizing *from* the
base-10 case.

According to <http://scott.sauyet.com/Javascript/Test/2010-06-16a/>, the
aurally-malformed one has chosen to use

var origPF = parseFloat;

if (!iBase || iBase == 10)
{
return origPF(s);
}


His main routine, as supplied, is therefore entirely useless for testing
native parseFloat. There, it (presumably) performs a conversion-speed
optimisation which diminishes utility as a source of reliable
conversions.


My function followed Thomas' lead and defaulted to the existing
(base-10) parseFloat function if the radix is not supplied or if the
radix is 10. This of course does treat base-10 as a special case.
There is some obvious justification for that, but there are clear
counter-arguments as well to having any such special cases.

Indeed. FIRST one should obtain a 100% accurate converter, using only
basic operations such as exact arithmetic (no rounding by use of the "+"
operator, for example), string splitting, character-to-number - all of
which operations will be well-tested in released ECMAscript.

SECOND, one can use that to check the quality of faster code to do the
same thing.

I'm afraid I don't follow this.

Write a good, slow, routine such as mine - call it PF(S, R).

Wrap it as

function FPF(S, R) {
return R == 10 ? parseFloat(S) : PF(S, R) }

in which the common case is faster; or merge by putting
if (R == 10) return parseFloat(S)
within function PF. Those are simplified examples, ignoring the case of
R absent.


Uggh!

This seems to be veering sharply away from the original idea of
pairing a version of parseFloat with the existing Number.toString() so
that we can reasonably switch representations, which I understood as
at least part of the goal of your original suggestion that "ECMA 6
should specify a Method whereby for ANY
Number X the result of X.toString(B) can be converted to the original
X ."

I did not want to imply disallowing the use of an exponent letter in a
base-10 float.
This suggestion also has the ugly feature that experience with other
languages could easily make one expect "1.23^45" to represent the
forty-fifth power of 1.23 rather than 1.23 * the forty-fifth power of
ten.

That's why I included @ in the suggestion.
Can you think of a good justification for mixing and matching a
base-10 exponent with a mantissa expressed in a different base? I
can't come up with one. I would suggest that the base be used for all
digits in the String format.

It all depends whether you are specifying formats that you would like to
output and read back, or planning to read in formats what you would NOT
like to output.

Compare date formats : I "always" prefer to output Gregorian dates as
yyyy-mm-dd or yyyy mm dd or yyyymmdd, but I am sometimes obliged to read
other forms such as 14 July 1789, and I sometimes provide a choice of
output forms such as dd.mm.yyyy.





My Web <URL:http://www.merlyn.demon.co.uk/js-maths.htm#BEA> now contains
and tests
function refParseFixed(IN, Rdx, Obj) { // Obj is an optional Object
I fairly strongly believe that for bases 2 to 36 it always gets the sign
and mantissa of the returned Number correct, and less strongly that it
always gets the exponent correct.

There, Obj, if present, must be an Object; it is given a string property
Bnry which is the mantissa of the result before rounding. It may not
remain.

It needs more testing.



Query : can a function, during execution, write a property to itself,
and if so how?
function F() {
myself.now = new Date() }
later:
alert(F.now) // see time of call
 
S

Scott Sauyet

Dr said:
In comp.lang.javascript message <4ba0b1f4-f63e-4c44-b87a-20a24b4953a4@q1
2g2000yqj.googlegroups.com>, Mon, 28 Jun 2010 07:34:06, Scott Sauyet



Actually, ECMA 262 is wrong.  Name "parseFloat" should mean that the
action "parse" is applied to a "Float" - and 123.456e78 is in floating-
point notation but 1234.5678 is in fixed=point notation.  The fact that
the result is a floating-point type is grammatically irrelevant.  A
better name would be "parseToFloat".

While I appreciate the distinction, I for one have never been
surprised by the semantics of a parseNoun() function. They always
take a String and return an item of type Noun. Perhaps it's because I
spent a fair bit of time in strongly typed languages, where the fact
that the parameter was a String and the result was of type Noun can be
noted at a glance.

Routines not using exponents such as we have been considering should be
called not "parseFloat" but "parseFixed".

Perhaps, but again I don't find this to be of major importance.

Given a parseFixed, one can make a parseFloat by wrapping it to hdle the
mantissa in with code to handle the exponent (which might also use
parseFixed or part thereof).

The "F" in my routine "BetterPF" has just changed its meaning.

I think it's relatively simple to change the regexes and the related
code in many of the existing implementation to handle the formats "e
+exp" or "E-exp" if we settle the question of the base of the
exponent. I would prefer to use the radix, but can (almost)
understand an argument for base-10.
According to <http://scott.sauyet.com/Javascript/Test/2010-06-16a/>, the
aurally-malformed one has chosen to use
^^^^^^^^^^^^^^^^^^^^^
:) "Malformed"?! I'm not sure that a bias in favor of blunt auditory
configurations should be promulgated here.

  var origPF = parseFloat;

    if (!iBase || iBase == 10)
    {
      return origPF(s);
    }

His main routine, as supplied, is therefore entirely useless for testing
native parseFloat.  There, it (presumably) performs a conversion-speed
optimisation which diminishes utility as a source of reliable
conversions.

You seem to be on a different path than I'm following. I understand
that you're looking for a reliable-even-if-inefficient converter of
string representations of base-n numbers to floating point numbers.
I'm less interested in that than in a practical-even-if-less-provably-
correct version.

Indeed.  FIRST one should obtain a 100% accurate converter, using only
basic operations such as exact arithmetic (no rounding by use of the "+"
operator, for example), string splitting, character-to-number - all of
which operations will be well-tested in released ECMAscript.

SECOND, one can use that to check the quality of faster code to do the
same thing.

But what is your basis for demonstrating the quality of a converter?
If a String is in the proper format to represent a base-n number and
that number is representable as an IEEE-754 floating point number,
should our algorithm choose the closest IEEE-754 value, subject to the
standard rounding rules? If so, how does one go about demonstrating
the accuracy? If not, what is the standard?

Write a good, slow, routine such as mine - call it PF(S, R).

Wrap it as

        function FPF(S, R) {
          return R == 10 ? parseFloat(S) : PF(S, R) }

in which the common case is faster; or merge by putting
          if (R == 10) return parseFloat(S)
within function PF.  Those are simplified examples, ignoring the case of
R absent.

Yes, but you're assuming that we can in some straightforward way show
that an unwrapped function or some other parseFloat is as accurate as
possible. I don't know if this can be done, and if you think it can,
I would love to see your evidence.

I did not want to imply disallowing the use of an exponent letter in a
base-10 float.

An alternative to that, though, is to require the exponent sign. That
would entirely disambiguate the possibilities. That is, unless we
made a (quite possibly reasonable) exception for base-10, we would not
allow "6.02214179e23", only "6.02214179e+23".
That's why I included @ in the suggestion.

I think e+, e-, E+, E- would be clearer and would not be overly
restrictive.

It all depends whether you are specifying formats that you would like to
output and read back, or planning to read in formats what you would NOT
like to output.

I understand Postel's law, but the only extension of the possible
output of toString(radix) I would like to cover is additional digits.
[ ... ]

My Web <URL:http://www.merlyn.demon.co.uk/js-maths.htm#BEA> now contains
and tests
     function refParseFixed(IN, Rdx, Obj) { // Obj is an optional Object
I fairly strongly believe that for bases 2 to 36 it always gets the sign
and mantissa of the returned Number correct, and less strongly that it
always gets the exponent correct.

Although its goal is somewhat different from the other functions on
the page, I did include it on my latest test page:

<http://scott.sauyet.com/Javascript/Test/2010-06-29a/>
[ ... ]

It needs more testing.

Query : can a function, during execution, write a property to itself,
and if so how?
        function F() {
           myself.now = new Date() }
later:
        alert(F.now) // see time of call

Yes, it's very easy for functions defined like that. Simply

F.now = new Date();
 
D

Dr J R Stockton

In comp.lang.javascript message <07c28fab-b585-4a49-8f70-50f5c8f30425@i3
1g2000yqm.googlegroups.com>, Tue, 29 Jun 2010 20:12:53, Scott Sauyet
Dr J R Stockton wrote:


You seem to be on a different path than I'm following.

Not really; I'm just ahead of you, and perhaps past where you were
intending to stop. I've written my comparatively fast and imperfectly
accurate routines, now parsFlotA parsFlotB parsFlotC parsFlotD.

I understand
that you're looking for a reliable-even-if-inefficient converter of
string representations of base-n numbers to floating point numbers.
I'm less interested in that than in a practical-even-if-less-provably-
correct version.

There are, evidently, many ways of getting an approximate answer,
especially if ECMA string to/from number routines are used. If you look
at what I've found about some of the major-browser implementations, you
will see while anything using their conversion routines cannot
reasonably be trusted cross-browser, unless it is compared cross-browser
with a known-good routine.

Finding a digit 2 in a binary number string is like
hearing the 13th stroke of a church clock.


But what is your basis for demonstrating the quality of a converter?
If a String is in the proper format to represent a base-n number and
that number is representable as an IEEE-754 floating point number,
should our algorithm choose the closest IEEE-754 value, subject to the
standard rounding rules?


It is that others can examine my code and see that it must give the
right answer. At present, that's fairly easy for the sign and mantissa.
It's a bit harder for the exponent; but big errors are not deceptive,
even though they may be annoying. Any reasonable rounding rule can be
applied without difficulty.


Yes, but you're assuming that we can in some straightforward way show
that an unwrapped function or some other parseFloat is as accurate as
possible. I don't know if this can be done, and if you think it can,
I would love to see your evidence.

It is <URL:http://www.merlyn.demon.co.uk/js-maths.htm#BEA>, once seen to
have been debugged and once the comment is adjusted so that a sufficient
number of people can understand the code. It uses the method that one
would use with pencil and paper.

It is easy to get parseFloat(S, R) fully accurate. Take the part before
the point and keep halving it in base-R arithmetic, pushing the
remainders until there is nothing left, and reverse them. Take the part
after the point and keep doubling it in base-R arithmetic, pushing the
remainders until one has 54 (sic) bits, of which the first will be a 1.
The 54th alone is sufficient to tell whether 1 has to be added to the
53rd. One now has the bits needed for the mantissa of an IEEE Double.
Start with zero and keep doubling and adding in to get what will be the
value after scaling in the exponent. Then consider whether there are
any special cases : "0.0" is such (since the code suggested so far will
fill the memory with zero bits while hoping to find a 1 bit); just test
the string for it and if found return a correctly-signed zero.

Exponent notation, once parsed for pattern, is easy if the exponent is
to the same radix; for approximate results, parseInt the exponent and
multiply/divide it in enough times (or trust Math.pow(Rdx, Expo)), and
for my method just shift the point in the string at the beginning.

I think e+, e-, E+, E- would be clearer and would not be overly
restrictive.

One could, for radix not 10, use lower case for the digits and upper-
case E for the separator.

Although its goal is somewhat different from the other functions on
the page, I did include it on my latest test page:

<http://scott.sauyet.com/Javascript/Test/2010-06-29a/>
<http://scott.sauyet.com/Javascript/Test/2010-06-29a/index.phps>

It's not really ready for that, unless you have reviewed and tested it
comprehensively. Today's version is different. Tomorrow's will be
different again. Give your users a textarea into which they can paste
code for test.

Also, if you examine the first of those of your pages, you find in "John
Stockton 3" a visible and invalid line
for (K=0, Cy=0 ; K= 0) Scale /= 2
but in my real code there are a few other lines between the second K and
the following =. Your innerHTML needs to be processed by something like
function SafeHTML(S) {
return S.split("&").join("&amp;").split("<").join("&lt;").
split(">").join("&gt;") } // IAS
if it may contain '<' '>' or '&' ('<' '>' do not always *need* to be
replaced; but they always can be).



Yes, it's very easy for functions defined like that. Simply

F.now = new Date();

function Fn() { alert(Fn.now) ; Fn.now = new Date() ; alert(1) }
Fn()
alert(Fn.now)
Fn()

works. I must have done something else wrong when trying to do
something like that. Thanks.


<http://www.bbc.co.uk/radio7/programmes/schedules>
links to John Major on Cricket.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
rlyn.invalid>, Thu, 1 Jul 2010 23:38:20, Dr J R Stockton
It is <URL:http://www.merlyn.demon.co.uk/js-maths.htm#BEA>, once seen to
have been debugged and once the comment is adjusted so that a sufficient
number of people can understand the code. It uses the method that one
would use with pencil and paper.


That seems completed. For radix 10, it agrees with parseFloat 99.98% of
the time in all browsers, otherwise differing only slightly. No
exponents. AFAICS, it should always be exact, rounding up for 0.5 LSB &
above.



function refParseFixed(IN, Rdx) { var Tmp, Sgn = +1, J = 0, Scale
Digits = "0123456789abcdefghijklmnopqrstuvwxyz"
Tmp = IN.charAt(0)
if (Tmp == "-" || Tmp == "+") { J = 1
if (Tmp == "-") Sgn = -1 }

var Num = Int = [], Frc = [], K = IN.length, Cy = true, Bin = []
while (J < K) { Tmp = IN.charAt(J++)
if (Tmp == "." && Num == Int) { Num = Frc ; continue }
Tmp = Digits.indexOf(Tmp.toLowerCase())
if (Tmp < 0 || Tmp >= Rdx) break
if (Tmp > 0) Cy = false
Num.push(Tmp) } // arrays now hold digit Numbers
if (Cy) return Sgn*0 // Zero (otherwise loops forever)

// Process integer part :
while (J = Int.length) { // not ==
for (K=0, Cy=0 ; K<J ; K++) {
Tmp = Cy * Rdx + Int[K] ; Cy = Tmp % 2 ; Int[K] = (Tmp-Cy) / 2 }
Bin.push(Cy)
while (Int[0] == 0) Int.shift() }
Bin.reverse()

while (Bin.length && Bin[0]==0) Bin.shift() // Omit any ldg zeroes
J = Bin.length - 54 ; Scale = 0.5 ; while (--J >= 0) Scale /= 2

// Process fractional part :
while (Bin.length < 54) { Cy = 0 ; K = Frc.length
while (K--) {
Tmp = Frc[K] * 2 + Cy ; Cy = +(Tmp>=Rdx) ; Frc[K] = Tmp % Rdx }
if (Bin.length || Cy == 1) Bin.push(Cy)
Scale *= 2 }

Bin[52] += Bin[53] // Rounding: now use Bin[0..52]

// Evaluate Bin and scale it :
for (J = 0, Num = 0 ; J < 53 ; J++) { Num *= 2 ; Num += Bin[J] }
return Sgn * Num / Scale } // end refParseFixed
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,566
Members
47,202
Latest member
misc.

Latest Threads

Top