From: Evertjan. on
Ry Nohryb wrote on 27 mei 2010 in comp.lang.javascript:

> String.prototype.toFP= function (base, digits, r, w, n) {
> digits= "0123456789abcdefghijklmnopqrstuvwxyz", r= 0;
> w= (n= this.toLowerCase().split('.'))[0].length;
> n.join('').split('').forEach(function (s) {
> r+= digits.indexOf(s) * Math.pow(base, --w) });
> return r;
>};
>

Nice!

since all non-'digit' chars would count as -1,
I would test for that,
as that makes debugging extreemly difficult.

String.prototype.toFP= function (base, digits, r, w, n) {
if (/[^0-9a-z\.]/i.test(this)) return NaN; // <<<---
digits= "0123456789abcdefghijklmnopqrstuvwxyz", r= 0;
w= (n= this.toLowerCase().split('.'))[0].length;
n.join('').split('').forEach(function (s) {
r+= digits.indexOf(s) * Math.pow(base, --w) });
return r;
};



--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
From: Ry Nohryb on
On May 27, 3:49 pm, "Evertjan." <exjxw.hannivo...(a)interxnl.net> wrote:
>
> Nice!
>
> since all non-'digit' chars would count as -1,
> I would test for that,
> as that makes debugging extreemly difficult.
>
> String.prototype.toFP= function (base, digits, r, w, n) {
>   if (/[^0-9a-z\.]/i.test(this)) return NaN; // <<<---
>   digits= "0123456789abcdefghijklmnopqrstuvwxyz", r= 0;
>   w= (n= this.toLowerCase().split('.'))[0].length;
>   n.join('').split('').forEach(function (s) {
>     r+= digits.indexOf(s) * Math.pow(base, --w) });
>   return r;
> };

Yes, good idea. And instead of n.join('').split('').forEach(f) an
[].forEach.call(n.join(''), f)... might be faster:

String.prototype.toFP= function (base, digits, w, n, r) {
if (/[^0-9a-z\.]/i.test(this)) return NaN;
digits= "0123456789abcdefghijklmnopqrstuvwxyz";
w= (n= this.toLowerCase().split('.'))[r= 0].length;
n.forEach.call(n.join(''), function (s) {
r+= digits.indexOf(s) * Math.pow(base, --w) });
return r;
};

What do we do with the sign ?
--
Jorge.
From: Evertjan. on
Ry Nohryb wrote on 27 mei 2010 in comp.lang.javascript:

> On May 27, 3:49�pm, "Evertjan." <exjxw.hannivo...(a)interxnl.net> wrote:
>>
>> Nice!
>>
>> since all non-'digit' chars would count as -1,
>> I would test for that,
>> as that makes debugging extreemly difficult.
>>
>> String.prototype.toFP= function (base, digits, r, w, n) {
>> � if (/[^0-9a-z\.]/i.test(this)) return NaN; // <<<---
>> � digits= "0123456789abcdefghijklmnopqrstuvwxyz", r= 0;
>> � w= (n= this.toLowerCase().split('.'))[0].length;
>> � n.join('').split('').forEach(function (s) {
>> � � r+= digits.indexOf(s) * Math.pow(base, --w) });
>> � return r;
>> };
>
> Yes, good idea. And instead of n.join('').split('').forEach(f) an
> [].forEach.call(n.join(''), f)... might be faster:
>
> String.prototype.toFP= function (base, digits, w, n, r) {
> if (/[^0-9a-z\.]/i.test(this)) return NaN;
> digits= "0123456789abcdefghijklmnopqrstuvwxyz";
> w= (n= this.toLowerCase().split('.'))[r= 0].length;
> n.forEach.call(n.join(''), function (s) {
> r+= digits.indexOf(s) * Math.pow(base, --w) });
> return r;
>};
>
> What do we do with the sign ?


this2 = this;
minus = 1;
if (this2.substr(0,1)=='-') {
this2 = this2.substr(1); // or .slice()?
minus = -1;
};
..........this2.........
return minus*r;



--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
From: Thomas 'PointedEars' Lahn on
Dr J R Stockton wrote:

> Some may not have noted that Number.toString(16) handles non-integers.
> Math.PI.toString(16) -> 3.243f6a8885a3
> 1e44.toString(16) -> 47bf19673df53000000000000000000000000
> Math.random().toString(2) => 0 . /[01]{1,53}/
>
> ECMA 262 (5) 15.7.4.2 Number.prototype.toString ( [ radix ] )
> makes no mention of non-integers.

It does not have to mention non-integers as all Number values are internally
represented as IEEE-754 double-precision floating-point values, which by
definition includes non-integers.

| If radix not present or is undefined the Number 10 is used as the value of
| radix. If ToInteger(radix) is the Number 10 then this Number value is
| given as an argument to the ToString abstract operation; the resulting
| String value is returned.
|
| [...]
| If ToInteger(radix) is an integer from 2 to 36, but not 10, the result is
| a String representation of this Number value using the specified radix.
| Letters a-z are used for digits with values 10 through 35. The precise
| algorithm is implementation-dependent if the radix is not 10, however the
| algorithm should be a generalization of that specified in 9.8.1.

> A Hex integer string H can be turned into a Number by
> + ( "0x" + H )

Or simply parseInt(H, 16).

> but that does not work for a Hex fraction string. Is there in fact an
> easy built-in way of converting non-integer Hex strings to Number?

No, I don't think so. Obviously you could do this:

var s = "f.0c";
var f = (s.match(/\.([\da-f]+)/i) || [, "0"])[1];

/* 15.046875 = 15 + 12 * Math.pow(16, -2) */
var n = parseInt(s, 16) + parseInt(f, 16) / Math.pow(16, f.length);

> Otherwise, I suggest 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
> (disregarding the sign of zero).

It would suffice if parseFloat() could take a second argument to specify the
base, as does parseInt(). But while it would be good to have it specified
in _ECMAScript Ed._ 6 ("Harmony"), I do not think we really need ES6 (and
probably to wait another 10 years) for that. It could, for example, be
implemented in JavaScript 1.9 as can be expected from Firefox 4.0, and then,
through competition, copied by other implementations like so many other
features before.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
From: Ry Nohryb on
On May 27, 11:07 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de>
wrote:
> (...)
>   var s = "f.0c";
>   var f = (s.match(/\.([\da-f]+)/i) || [, "0"])[1];
>
>   /* 15.046875 = 15 + 12 * Math.pow(16, -2) */
>   var n = parseInt(s, 16) + parseInt(f, 16) / Math.pow(16, f.length);
> (...)

We're almost there, but not yet:

function pointyParseFloat (s, base) {
var f = (s.match(/\.([\da-f]+)/i) || [, "0"])[1];
return parseInt(s, base) + parseInt(f, base) / Math.pow(base,
f.length);
}

pointyParseFloat(Math.PI.toString(16), 16)
--> 3.141592653589793

pointyParseFloat(Math.PI.toString(33), 33)
--> 3.121212121212121

pointyParseFloat((-Math.PI).toString(16), 16)
--> -2.858407346410207

String.prototype.toFP= function (base, digits, w, n, r) {
if (/[^0-9a-z\.]/i.test(this)) return NaN;
digits= "0123456789abcdefghijklmnopqrstuvwxyz";
r= parseInt((n= this.toLowerCase().split('.'))[w= 0], base);
n.forEach.call(n[1], function (s) {
r+= digits.indexOf(s) * Math.pow(base, --w) });
return r;
};

(Math.PI).toString(16).toFP(16)
--> 3.141592653589793

(Math.PI).toString(33).toFP(33)
--> 3.141592653589793

(-Math.PI).toString(33).toFP(33)
--> NaN

--
Jorge.