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

R

Ry Nohryb

(...) you are calling the callback futilely at least 886 times in
V8 because precision does not suffice to represent the factor (...)

[*] FIXED:

String.prototype.toFP= function (base, d, w, n, r, s, pw) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
d= "0123456789abcdefghijklmnopqrstuvwxyz";
s= (r= parseInt((n= this.split('.'))[w= 0], base)) < 0 ? -1 : 1;
n= n[1].toLowerCase().split('');
while(n.length && (pw=Math.pow(base,--w))) r
+=s*d.indexOf(n.shift())*pw;
return r;
};

for (var base=2; base <37; base++) console.log([base,
Math.PI.toString(base).toFP(base)])
-->
[2, 3.141592653589793]
[3, 3.141592653589794]
[4, 3.141592653589793]
[5, 3.1415926535897936]
[6, 3.141592653589793]
[7, 3.141592653589794]
[8, 3.141592653589793]
[9, 3.141592653589794]
[10, 3.141592653589793]
[11, 3.141592653589793]
[12, 3.141592653589793]
[13, 3.141592653589793]
[14, 3.141592653589793]
[15, 3.1415926535897936]
[16, 3.141592653589793]
[17, 3.141592653589793]
[18, 3.141592653589794]
[19, 3.1415926535897922]
[20, 3.141592653589793]
[21, 3.1415926535897936]
[22, 3.1415926535897927]
[23, 3.141592653589793]
[24, 3.141592653589793]
[25, 3.1415926535897936]
[26, 3.141592653589793]
[27, 3.1415926535897927]
[28, 3.141592653589794]
[29, 3.141592653589793]
[30, 3.141592653589793]
[31, 3.141592653589793]
[32, 3.141592653589793]
[33, 3.141592653589793]
[34, 3.141592653589793]
[35, 3.141592653589793]
[36, 3.141592653589793]
 
E

Evertjan.

Dr J R Stockton wrote on 28 mei 2010 in comp.lang.javascript:
In comp.lang.javascript message <[email protected]>


You have both missed the point. I wrote :

Perhaps, John, we missed YOUR point.

However we were [or at least I was] just contemplating a general function
for conversion of any root[1..36] floating point string to number value.

Such functions are much safer explicit than embedded,
if speed is not the essense,
as any bug can more easily be delt with,
as you, as king of the embedded bug detectives,
should know.

;-)

btw: in root 1 only the zero value can be expressed.
 
R

Ry Nohryb

String.prototype.toFP= function (base, d, w, n, r, s, pw) {
  if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
  d= "0123456789abcdefghijklmnopqrstuvwxyz";
  s= (r= parseInt((n= this.split('.'))[w= 0], base)) < 0 ? -1 :1;
  n= n[1].toLowerCase().split('');
  while(n.length && (pw=Math.pow(base,--w))) r
+=s*d.indexOf(n.shift())*pw;
  return r;

};

(...)

Take 3: this one uses the same algorithm of my first post, but, if the
divisor (Math.pow(base, fractionalPartStr.length) is too big
(Infinity) it trims fractionalPartStr down until isFinite(divisor):

/* Tested in Safari, Chrome, Opera & FF */

String.prototype.toFP= function (base, n, r, w, div) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (w= (n= n[1]).length) {
/*trim until it's finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
r+= (r<0 ? -1:1)* parseInt(n.substr(0, w), base)/ div;
}
}
return r;
};

for (var base=2; base <37; base++) console.log([base,
Math.PI.toString(base).toFP(base)])
-->
[2, 3.141592653589793]
[3, 3.141592653589793]
[4, 3.141592653589793]
[5, 3.141592653589793]
[6, 3.141592653589793]
[7, 3.141592653589793]
[8, 3.141592653589793]
[9, 3.141592653589793]
[10, 3.141592653589793]
[11, 3.141592653589793]
[12, 3.141592653589793]
[13, 3.141592653589793]
[14, 3.141592653589793]
[15, 3.141592653589793]
[16, 3.141592653589793]
[17, 3.141592653589793]
[18, 3.141592653589793]
[19, 3.141592653589793]
[20, 3.141592653589793]
[21, 3.141592653589793]
[22, 3.141592653589793]
[23, 3.141592653589793]
[24, 3.141592653589793]
[25, 3.141592653589793]
[26, 3.141592653589793]
[27, 3.141592653589793]
[28, 3.141592653589793]
[29, 3.141592653589793]
[30, 3.141592653589793]
[31, 3.141592653589793]
[32, 3.141592653589793]
[33, 3.141592653589793]
[34, 3.141592653589793]
[35, 3.141592653589793]
[36, 3.141592653589793]

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

Dr J R Stockton

In comp.lang.javascript message <[email protected]>,
Fri, 28 May 2010 14:34:28, Thomas 'PointedEars' Lahn
Yes, good catch; we need to consider the sign with addition, e.g.:

var s = (-Math.PI).toString(16);
var i = parseInt(s, 16);
var f = (s.match(/\.([\da-f]+)/i) || [, "0"])[1];
var n = i + (i < 0 ? -1 : 1) * parseInt(f, 16) / Math.pow(16, f.length);

You need to consider it more effectively, and to test adequately.

That indeed gives -3.141592653589793; but use instead Math.PI/10 and it
gives 0.3141592653589793. Whenever parseInt(s, 16) gives a zero, your
code will give a positive result.

Search the archives covering the 200x decade, and you will see that the
relevant facts are known.
 
T

Thomas 'PointedEars' Lahn

Dr said:
Thomas 'PointedEars' Lahn posted:
Yes, good catch; we need to consider the sign with addition, e.g.:

var s = (-Math.PI).toString(16);
var i = parseInt(s, 16);
var f = (s.match(/\.([\da-f]+)/i) || [, "0"])[1];
var n = i + (i < 0 ? -1 : 1) * parseInt(f, 16) / Math.pow(16, f.length);

You need to consider it more effectively, and to test adequately.

Do you know what "quick hack" means?
That indeed gives -3.141592653589793; but use instead Math.PI/10 and it
gives 0.3141592653589793. Whenever parseInt(s, 16) gives a zero, your
code will give a positive result.

ACK, thanks. ISTM that checking whether the first character of the
representation is a `-' solves this particular problem. Again, largely
untested:

var s = (-Math.PI/10).toString(16);
var i = parseInt(s, 16);
var f = (s.match(/\.([\da-f]{1,198})/i) || [, "0"])[1];
var n = i + (s.charAt(0) == "-" ? -1 : 1) * parseInt(f, 16) / Math.pow(16,
f.length);

But if `s' would be user-defined, it could have leading whitespace, so:

var n = i + (/^\s*-/.test(s) ? -1 : 1) * parseInt(f, 16) / Math.pow(16,
f.length);


PointedEars
 
R

Ry Nohryb

(...)

  var s = (-Math.PI/10).toString(16);
  var i = parseInt(s, 16);
  var f = (s.match(/\.([\da-f]{1,198})/i) || [, "0"])[1];
___________________________________^^^____________________

There's no need to trim f to 198 chars: Math.pow(16, n) overflows at n
=== 256, not @ 199.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>
Dr J R Stockton wrote on 28 mei 2010 in comp.lang.javascript:
However we were [or at least I was] just contemplating a general function
for conversion of any root[1..36] floating point string to number value.

Remember to include isNaN & !isFinite testing.
Such functions are much safer explicit than embedded,

Sometimes. The advantage of an embedded bug is that someone else is
more likely to find it first, and get it fixed.

Opera 10.10, but not Opera 10.53 : Number.toString(radix) ignores
radix.
btw: in root 1 only the zero value can be expressed.

Eh?
 
T

Thomas 'PointedEars' Lahn

Ry said:
Thomas said:
(...)

var s = (-Math.PI/10).toString(16);
var i = parseInt(s, 16);
var f = (s.match(/\.([\da-f]{1,198})/i) || [, "0"])[1];
___________________________________^^^____________________

There's no need to trim f to 198 chars:

Not in this example, but for the general case without an adaptive algorithm.
Math.pow(16, n) overflows at n === 256, not @ 199.

But parseInt(s, 36) "overflows" at more than 198 consecutive "z"s in s.


PointedEars
 
R

Ry Nohryb

Ry said:
Thomas said:
(...)
var s = (-Math.PI/10).toString(16);
var i = parseInt(s, 16);
var f = (s.match(/\.([\da-f]{1,198})/i) || [, "0"])[1]; ___________________________________^^^____________________

There's no need to trim f to 198 chars:

Not in this example, but for the general case without an adaptive algorithm.
Math.pow(16, n) overflows at n === 256, not @ 199.

But parseInt(s, 36) "overflows" at more than 198 consecutive "z"s in s.

The fractional part can never be > ( the divisor -1 ), that's why
you've got to look at the divisor (Math.pow(base, len) instead, as I
did in my "take 3", and adjust len accordingly (to both the base and
the fractional part string length):

/* Tested in Safari, Chrome, Opera & FF */
String.prototype.toFP= function (base, n, r, w, div) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (w= (n= n[1]).length) {
/*trim until it's finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
r+= (r<0 ? -1:1)* parseInt(n.substr(0, w), base)/ div;
}
}
return r;
};

for (var base=2; base <37; base++) console.log([base,
Math.PI.toString(base).toFP(base)])

--> === Math.PI
 
R

Ry Nohryb

/* Tested in Safari, Chrome, Opera & FF */

String.prototype.toFP= function (base, n, r, w, div) {
  if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
  n= this.split('.');
  if (isFinite(r= parseInt(n[0], base))) {
    if (w= (n= n[1]).length) {
      /*trim until it's finite*/
      while (!isFinite(div= Math.pow(base, w))) w--;
      r+= (r<0 ? -1:1)* parseInt(n.substr(0, w), base)/ div;
    }
  }
  return r;
};


****** BUG FIX:

/* Tested in Safari, Chrome, Opera & FF */

String.prototype.toFP= function (base, n, r, w, div, s) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (n[1] && (w= n[1].length)) {
/*trim until div is finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
/*Tests sign properly for -0.xxxx*/
s= (r || parseInt(n[0]+ "1", base)) < 0 ? -1:1;
r+= s* parseInt(n[1].substr(0, w), base)/ div;
}
}
return r;
};

"ff".toFP(16) /* integer input no longer throws */
--> 255

(-Math.PI/10).toString(16).toFP(16) /* proper sign detection */
--> -0.3141592653589793
 
D

David Mark

In comp.lang.javascript message <[email protected]>
Dr J R Stockton wrote on 28 mei 2010 in comp.lang.javascript:
In comp.lang.javascript message <[email protected]>
, Thu, 27 May 2010 18:16:34, Evertjan. <[email protected]>
posted:
However we were [or at least I was] just contemplating a general function
for conversion of any root[1..36] floating point string to number value.

Remember to include isNaN & !isFinite testing.
Such functions are much safer explicit than embedded,

Sometimes.  The advantage of an embedded bug is that someone else is
more likely to find it first, and get it fixed.

Opera 10.10, but not Opera 10.53 : Number.toString(radix) ignores
radix.

Not from what I've seen (just tested it). I just happened to be
working on some code that relies on toString to work with a radix and
your comment was a real spit-take moment.

Which Opera 10.10 are you testing?
 
T

Thomas 'PointedEars' Lahn

JFTR: Number.toString !== Number.prototype.toString.
Not from what I've seen (just tested it). I just happened to be
working on some code that relies on toString to work with a radix and
your comment was a real spit-take moment.

Which Opera 10.10 are you testing?

WFM, too. (128).toString(36) === "3k" in "Opera/9.80 (X11; Linux i686; U;
en) Presto/2.2.15 Version/10.10" (Build 4742) and "Opera/9.80 (Windows NT
5.1; U; en) Presto/2.2.15 Version/10.10" (Build 1893).


PointedEars
 
D

David Mark

JFTR: Number.toString !== Number.prototype.toString.

Right. Number.toString === Function.prototype.toString
WFM, too.  (128).toString(36) === "3k" in "Opera/9.80 (X11; Linuxi686; U;
en) Presto/2.2.15 Version/10.10" (Build 4742) and "Opera/9.80 (Windows NT
5.1; U; en) Presto/2.2.15 Version/10.10" (Build 1893).

I'd be pretty shocked if it didn't. Would be a hell of a regression.
 
E

Evertjan.

Ry Nohryb wrote on 31 mei 2010 in comp.lang.javascript:
String.prototype.toFP= function (base, n, r, w, div, s) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (n[1] && (w= n[1].length)) {
/*trim until div is finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
/*Tests sign properly for -0.xxxx*/
s= (r || parseInt(n[0]+ "1", base)) < 0 ? -1:1;


s= parseInt(n[0]+ '1', base)<0 ? -1:1;

r+= s* parseInt(n[1].substr(0, w), base)/ div;
}
}
return r;
};
 
E

Evertjan.

Evertjan. wrote on 31 mei 2010 in comp.lang.javascript:
Ry Nohryb wrote on 31 mei 2010 in comp.lang.javascript:
String.prototype.toFP= function (base, n, r, w, div, s) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;
n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (n[1] && (w= n[1].length)) {
/*trim until div is finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
/*Tests sign properly for -0.xxxx*/
s= (r || parseInt(n[0]+ "1", base)) < 0 ? -1:1;


s= parseInt(n[0]+ '1', base)<0 ? -1:1;

Or even:

s= n[0][0]=='-' ?-1 :1;
r+= s* parseInt(n[1].substr(0, w), base)/ div;
}
}
return r;
};
 
E

Evertjan.

Evertjan. wrote on 31 mei 2010 in comp.lang.javascript:
Evertjan. wrote on 31 mei 2010 in comp.lang.javascript:
Ry Nohryb wrote on 31 mei 2010 in comp.lang.javascript:
String.prototype.toFP= function (base, n, r, w, div, s) {
if (/[^0-9a-z\.+-]/i.test(this)) return NaN;


This test is not enough now, meseems:

a = '12345abc.5def'
document.write((a.toFP(10)) // 12345.0005

use:

var re = base>10 ?'a-'+String.fromCharCode(86+base) :'';
re = new RegExp('[^0-9'+re+'\.+-]','i');
if (re.test(this)) return NaN;

and add:

if (/[+-]/.test(this.substr(1))) return NaN; //+- must be in position 0
if (this.replace(/[^\.]+/g,'').length>1) return NaN; // count of . <=1


n= this.split('.');
if (isFinite(r= parseInt(n[0], base))) {
if (n[1] && (w= n[1].length)) {
/*trim until div is finite*/
while (!isFinite(div= Math.pow(base, w))) w--;
/*Tests sign properly for -0.xxxx*/
s= (r || parseInt(n[0]+ "1", base)) < 0 ? -1:1;


s= parseInt(n[0]+ '1', base)<0 ? -1:1;

Or even:

s= n[0][0]=='-' ?-1 :1;
r+= s* parseInt(n[1].substr(0, w), base)/ div;
}
}
return r;
};
 
E

Evertjan.

Stefan Weiss wrote on 31 mei 2010 in comp.lang.javascript:
In a unary system it's more usual to count like this:

1
11
111
1111

Not all values can be expressed this way (for example, 0 or 1.05), but
at least you get more values that just the zero.

I do not agree in the sense of radixed position dependent strings.

You are mixing position dependent and position independent notation,
and not comparing radix notations.

Your unary system is not based on the extrapolation of such position
dependent numeric string notation.
You even erroneously introduce a position by your right justification.
In your system the zero is an empty string, btw.

Hebrew numbers, while having characters for 1..9 10 20 30 etc, is also
totally position independent, while Latin I II III IV is semi-dependent.
In such systems the zero cannot exist for logical reasons.

So I hold that "radix 1" notation only can specify the zero value, since
that is there only character available, even though a theoretical position
notation exists.

The "radix 0" notation is even more esoteric, as all positions can only be
empty. This does not mean that an empty string is zero, btw.
 
E

Evertjan.

Stefan Weiss wrote on 31 mei 2010 in comp.lang.javascript:
I never mentioned strings

Implicitly, the notation of a number in a certain radix MUST BE in a
string.
- the concept of an empty string doesn't
make sense on paper, or on the wall of a prison cell.

Oh, but it does, OT as we are talking Javascript number values.

The prisoner has no dilemma in carving the first vertical stroke ony after
his first day in his cell. Thae absense of that stroke is a fair definition
of zero completed days.
If the unary notation I used is position independent, how can right or
left justification be an error?

You sowed a right justification, implying there rightmost value to be the
first, either in error, or, if you deny that, in falsehood?

Right, and now let's try fractional radices!

RIGHT, then we are LEFT with far more interesting negative radices.

Would they count as uprooted free radicals,
the oxigen of string notation of numbers?

Or is this only string theory?
 

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
473,779
Messages
2,569,606
Members
45,239
Latest member
Alex Young

Latest Threads

Top