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

R

Ry Nohryb

I cannot confirm this.  Where have you tested it?

Safari / Mac:
navigator.userAgent
--> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us)
AppleWebKit/534.1+ (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7"
 
R

Ry Nohryb

Your code style is being frowned upon by several knowledgable people here..

♪ We're all ♫ free ♩ to frown ♫

Or not ?

E.g., I have just frowned upon your 23 LOC parsefloat() that doesn't
work.
 
T

Thomas 'PointedEars' Lahn

Ry said:
Safari / Mac:
navigator.userAgent
--> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us)
AppleWebKit/534.1+ (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7"

Thanks, I am seeing this in Google Chrome 5.0.375.55 beta for Linux (V8
2.1), too.

The reason of this is apparently that the fractional part of
"3.4m6dn4ow9qwe210nr3u0cdqkcnrbmwlh7kmfeapn9fijt38kie44jvdqh2vfrd6ogbvu
rnjq2bqkbr01f97av5k7uaffclrl3hmt2glugpaqe422qgfn81ca8pa73pmt51ewqo9234c
km2twg1qgwmahsv1pdti9bug3bjc9w0sn9ul421p5aanjnfuab9rq3bm5lchsu5aq6000no
i5wcf9c5p5idkgclha9j05bcupqqcb9h08dc3i2v2qcqjks96pgpkmangnavpt7tk6kvrfo
s0qq63iqrgv5nu2i8goh8tjmifwbwf9t3bvcd4r61tbqa05ca16ql0icacmucfcl1h3ceb1
hrdmhhmsp8ri842wn3nj97v7r5i9mdv135qo5jd9bn9chun8n1h11qlgt35mqksnn8ef4p6
kdade1d2t1bfigevwtjnjufm5sc9vhgq7qusio03g1ctrgmukjj5frghkmw1f1dhl4hvr7c
8slmplk66fb34twd9dwkvb16dfi8lbq8nvftmvwo2o4aukf0d252v3go1gtbgfbj8qoqtsf
8hpkkdfw9w686je30nmk6ojecalbc9ifs533e4gucpivw3327b1rc8a7qvqplce4o5agc9s
9h64lia1bker9hhbj7tq6saw68e7c6nqo37v97nbgl8bcgniv3g7ebvrwufnuqsqhlk6fee
7nsj348jwe0nstlnrjcet17sdksk7fo81rwtn6tknpo7lmcmskd4t5lebji6h6riabtauul
s2d49kgak0cu02fbwfklvn6jdlchkn7uwfa7qvncrfrw2umrhpja4hkwgrm261o8cf67c0a
lckiq428lpcvnjub55qkp15l90pbd47w9tupnf87iwjt8stpccka0scrqi7o6v8vmn1b73c
9f4r4g3m11ofcdw5rq7rv89s69mnoumfpark413hsogn5lb4qawo789t7oet5kfolb9ltn9
wm4iqlhi1glc5e2nd9q6jc6dghqcr5epkf2fde1rpd3ii2ouj7bq0pn16n4l28b85thc8ob
3bi7debdwogfnhfaif0v6h4k2i9k39fkrvmlc", which is the 33-ary representation
of Math.PI there, is parsed (because of its length) into `Infinity', while
in JavaScript 1.8.2 the representation is rounded to "3.4m6dn4ow9r" and
therefore the fractional part is not parsed into `Infinity'.

Therefore, it appears to be prudent to truncate the fractional part so that
it is not parsed into `Infinity'. A simple solution is to restrict the
number of characters matched by the regular expression, like:

... new RegExp("\\.([" + chars + "]{1,10})", "i") ...

A more sophisticated solution would be an adaptive algorithm that uses only
as many characters as possible so that the result would not be `Infinity'
given the numeric base. An implementation of that might be available
through the Mozilla sources.


BTW, in case you have not noticed yet, like Safari, Chrome has a Developer
menu (in the first main menu, below the Encoding menu item), which provides
access to the Developer tools, including a script console and a debugger
(which helped me to track this down). That makes using Firebug Lite in
Chrome unnecessary.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Johannes said:
Thomas 'PointedEars' Lahn :

That *could* end up being a circular definition, like Flew's "No true
Scotsman" argument, http://en.wikipedia.org/wiki/No_true_Scotsman
(If someone does not frown upon Jorge's code style, it shows that
that person is not *knowledgeable*.)

Yes, it could, if one would make that fallacy. However, the outcome of
reviews of Jorge's code style is not the (sole) defining property here.


PointedEars
 
R

Ry Nohryb

Safari / Mac:
navigator.userAgent
--> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us)
AppleWebKit/534.1+ (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7"

Thanks, I am seeing this in Google Chrome 5.0.375.55 beta for Linux (V8
2.1), too.

The reason of this is apparently that the fractional part of
"3.4m6dn4ow9qwe210nr3u0cdqkcnrbmwlh7kmfeapn9fijt38kie44jvdqh2vfrd6ogbvu
rnjq2bqkbr01f97av5k7uaffclrl3hmt2glugpaqe422qgfn81ca8pa73pmt51ewqo9234c
km2twg1qgwmahsv1pdti9bug3bjc9w0sn9ul421p5aanjnfuab9rq3bm5lchsu5aq6000no
i5wcf9c5p5idkgclha9j05bcupqqcb9h08dc3i2v2qcqjks96pgpkmangnavpt7tk6kvrfo
s0qq63iqrgv5nu2i8goh8tjmifwbwf9t3bvcd4r61tbqa05ca16ql0icacmucfcl1h3ceb1
hrdmhhmsp8ri842wn3nj97v7r5i9mdv135qo5jd9bn9chun8n1h11qlgt35mqksnn8ef4p6
kdade1d2t1bfigevwtjnjufm5sc9vhgq7qusio03g1ctrgmukjj5frghkmw1f1dhl4hvr7c
8slmplk66fb34twd9dwkvb16dfi8lbq8nvftmvwo2o4aukf0d252v3go1gtbgfbj8qoqtsf
8hpkkdfw9w686je30nmk6ojecalbc9ifs533e4gucpivw3327b1rc8a7qvqplce4o5agc9s
9h64lia1bker9hhbj7tq6saw68e7c6nqo37v97nbgl8bcgniv3g7ebvrwufnuqsqhlk6fee
7nsj348jwe0nstlnrjcet17sdksk7fo81rwtn6tknpo7lmcmskd4t5lebji6h6riabtauul
s2d49kgak0cu02fbwfklvn6jdlchkn7uwfa7qvncrfrw2umrhpja4hkwgrm261o8cf67c0a
lckiq428lpcvnjub55qkp15l90pbd47w9tupnf87iwjt8stpccka0scrqi7o6v8vmn1b73c
9f4r4g3m11ofcdw5rq7rv89s69mnoumfpark413hsogn5lb4qawo789t7oet5kfolb9ltn9
wm4iqlhi1glc5e2nd9q6jc6dghqcr5epkf2fde1rpd3ii2ouj7bq0pn16n4l28b85thc8ob
3bi7debdwogfnhfaif0v6h4k2i9k39fkrvmlc", which is the 33-ary representation
of Math.PI there, is parsed (because of its length) into `Infinity', while
in JavaScript 1.8.2 the representation is rounded to "3.4m6dn4ow9r" and
therefore the fractional part is not parsed into `Infinity'.

Therefore, it appears to be prudent to truncate the fractional part so that
it is not parsed into `Infinity'.  A simple solution is to restrict the
number of characters matched by the regular expression, like:

   ... new RegExp("\\.([" + chars + "]{1,10})", "i") ...

A more sophisticated solution would be an adaptive algorithm that uses only
as many characters as possible so that the result would not be `Infinity'
given the numeric base.  An implementation of that might be available
through the Mozilla sources.

No. A "more sophisticated solution" is to fix your broken algorithm:
you're parsing an amount which is less than 1 as an (probably)
enormous integer and then dividing it by another (probably) enormous
integer. That's the problem, not Chrome, your algorithm is the
culprit.

You're, as usual, heavily disoriented.
BTW, in case you have not noticed yet, like Safari, Chrome has a Developer
menu (in the first main menu, below the Encoding menu item), which provides
access to the Developer tools, including a script console and a debugger
(which helped me to track this down).  That makes using Firebug Lite in
Chrome unnecessary.

You're telling me ?

See: http://groups.google.com/group/comp.lang.javascript/msg/8e76deb9e1bc4441
 
R

Ry Nohryb

Personally, I consider his suggestions interesting and enlightening.
I wouldn't use them in production code destined to be maintained by
cheap labour, but then, this newsgroup is hardly entirely about writing
Web applications in an industrial environment, is it now ? (If it is,
where can I find discussions about the computer language javascript ?)

Thanks, :)
 
R

Ry Nohryb

(...)
where can I find discussions about the computer language javascript ?

Yeah, comp.lang.javascript definitely sounds alike, very much
suspiciously alike.
 
T

Thomas 'PointedEars' Lahn

Ry said:
Thomas said:
Ry said:
Thomas 'PointedEars' Lahn wrote:
Ry Nohryb wrote:
parseFloat(Math.PI.toString(33), 33)
--> NaN

I cannot confirm this. Where have you tested it?
Safari / Mac:
navigator.userAgent
--> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us)
AppleWebKit/534.1+ (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7"

Thanks, I am seeing this in Google Chrome 5.0.375.55 beta for Linux (V8
2.1), too.

The reason of this is apparently that the fractional part of
"3.4m6dn4ow9qwe210nr3u0cdqkcnrbmwlh7kmfeapn9fijt38kie44jvdqh2vfrd[...]",
which is the 33-aryrepresentation of Math.PI there, is parsed (because of
its length) into `Infinity', while in JavaScript 1.8.2 the representation
is rounded to "3.4m6dn4ow9r" and therefore the fractional part is not
parsed into `Infinity'.

Therefore, it appears to be prudent to truncate the fractional part so
that it is not parsed into `Infinity'. A simple solution is to restrict
the number of characters matched by the regular expression, like:

... new RegExp("\\.([" + chars + "]{1,10})", "i") ...

A more sophisticated solution would be an adaptive algorithm that uses
only as many characters as possible so that the result would not be
`Infinity' given the numeric base. An implementation of that might be
available through the Mozilla sources.

No. A "more sophisticated solution" is to fix your broken algorithm:
you're parsing an amount which is less than 1 as an (probably)
enormous integer

Less than 1? You don't know what you are talking about.
and then dividing it by another (probably) enormous integer. That's the
problem, not Chrome, your algorithm is the culprit.

As usual you fail to recognize the relevant cause-and-effect relationship.
The problem here is produced by the different implementations of
Number.prototype.toString(), although JavaScriptCore's/V8's behavior cannot
be considered a bug in the ECMAScript implementation, as I have already
indicated in my response to John Stockton.

By comparison you are splitting before you need to (parseInt() can take care
of the point), you are calling the callback futilely at least 886 times in
V8 because precision does not suffice to represent the factor, you fail to
handle the sign properly, and you lose precision every time you call the
callback and increment `r'.
You're, as usual, heavily disoriented.

Yeah, maybe that is why your code also fails to solve this problem:

,-<|
| (-Math.PI).toString(33).toFP(33)
| --> NaN
You're telling me ?

Don't be so vain.


PointedEars
 
R

Ry Nohryb

Yeah, maybe that is why your code also fails to solve this problem:

,-<|
| (-Math.PI).toString(33).toFP(33)
| --> NaN

You're not paying attention:
http://groups.google.com/group/comp.lang.javascript/msg/f0761684a6595c2a
String.prototype.toFP= function (base, d, w, n, r, s) {
  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) r+= s* d.indexOf(n.shift())* Math.pow(base, --w);
  return r;

};

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

Lasse Reichstein Nielsen

Ry Nohryb said:
String.prototype.toFP= function (base, digits, w, n, r) {

One argument against using unused parameters as local variable
declarations, that hasn't been mentioned yet, is that it might slow
down calling the function.

Simple test:

(function() {
function foo1(a,b,c,d,e) {
e=a;d=e;c=d;b=c;return b;
}
function foo2(a) {
var b,c,d,e;
e=a;d=e;c=d;b=c;return b;
}
var x = 42;
foo1(x);foo2(x); // Make sure they are compiled.
var t0 = Date.now();
for (var i = 0; i < 10000000; i++) {
x = foo1(x);
}
var t1 = Date.now();
for (var i = 0; i < 10000000; i++) {
x = foo2(x);
}
var t2 = Date.now();
alert([t1-t0,t2-t1]);
})()

Safari: 300, 179
Opera 10.54: 132, 116 (maybe not significant).
Chrome dev: 145, 90
Firefox and IE: no noticable difference.
(I also ran the tests with the two loops swapped, to see if going
first made a difference. It did a little in Firefox).

It also prevents the compiler from knowing the initial values
of the variables (but that should be irrelevant if they are
initialized before use on all paths anyway).

/L
 
R

Ry Nohryb

Don't be so vain.

I'm not, but I was well aware of that, since a long time ago (years).

And you, Mr. knows-it-all, the master flagellator of newbies, were not
aware -until today- of that debugger (it's both in Safari and in
Chrome: exactly the same: and you open it in both using exactly the
same keystrokes: cmd+option+i) almost TWO years after its
introduction ?

How would you have called that, in your usual (and particular)
tongue ? Completely clueless ? Total cluelessness ?

Let me LOL, please. Let me ROTFLOL.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>
Ry Nohryb wrote on 27 mei 2010 in comp.lang.javascript:

You have both missed the point. I wrote :
Is there in fact an
easy built-in way of converting non-integer Hex strings to Number?

to which the proper answers must be along the lines of "I cannot see
one" or "ECMA 262 #.##.# indicates that <brief> does it".

I can readily enough code that myself in various ways, the most obvious
being to use parseint(S, 16) for the integer part, split off the
fractional part, use parseInt(S, 16) on that, divide by Math.pow(16,
length) then add or subtract.

ISTM that parseInt("-0", 16) does indeed return -0.

S = "-45.6"
A = parseInt(S, 16)
if (S = S.split(".")[1])
A += (2*(1/A>0)-1) * parseInt(S, 16) / Math.pow(16, S.length)
// -> -69.375

That is undertested. A number string should always have a digit before
its basal separator if any. Have no non-digit terminator.

But that is, although easy, not built-in. Built-on means something like
using unary + rather than valueOf or getTime on a Date Object would be
if those two methods did not exist - an inconspicuous but useful fearure
of the language as specified, generally missing from non-normative
descriptions of the language.
 
R

Ry Nohryb

Ry Nohryb said:
String.prototype.toFP= function (base, digits, w, n, r) {

One argument against using unused parameters as local variable
declarations, that hasn't been mentioned yet, is that it might slow
down calling the function.

Simple test:

(function() {
 function foo1(a,b,c,d,e) {
   e=a;d=e;c=d;b=c;return b;
 }
 function foo2(a) {
   var b,c,d,e;
   e=a;d=e;c=d;b=c;return b;
 }
 var x = 42;
 foo1(x);foo2(x);  // Make sure they are compiled.
 var t0 = Date.now();
 for (var i = 0; i < 10000000; i++) {
   x = foo1(x);  
 }
 var t1 = Date.now();
 for (var i = 0; i < 10000000; i++) {
   x = foo2(x);  
 }
 var t2 = Date.now();
 alert([t1-t0,t2-t1]);

})()

Safari:      300, 179
Opera 10.54: 132, 116 (maybe not significant).
Chrome dev:  145, 90
Firefox and IE: no noticable difference.
(I also ran the tests with the two loops swapped, to see if going
first made a difference. It did a little in Firefox).

That's very interesting. Any clues as to why ? In any case, first of
all, thanks for sharing. Although imo such a small difference only
makes a difference in the rare cases when you're calling (ultra-short
and fassst) functions at a rate of tens of millions per second, which
is hardly a usual thing. After all, we're talking about differences of
+/-5ns per call, here: 5e-9 seconds, you've got to do quite a lot of
calls in order to notice that, or not ?
It also prevents the compiler from knowing the initial values
of the variables (but that should be irrelevant if they are
initialized before use on all paths anyway).

Ack.
 
R

Ry Nohryb

In comp.lang.javascript message <[email protected]>


You have both missed the point.  I wrote :


to which the proper answers must be along the lines of "I cannot see
one" or "ECMA 262 #.##.# indicates that <brief> does it".

Ok. There seems to be an easy way but it's not built-in.
I can readily enough code that myself in various ways, the most obvious
being to use parseint(S, 16) for the integer part, split off the
fractional part, use parseInt(S, 16) on that, divide by Math.pow(16,
length) then add or subtract.

ISTM that parseInt("-0", 16) does indeed return -0.

        S = "-45.6"
        A = parseInt(S, 16)
        if (S = S.split(".")[1])
          A += (2*(1/A>0)-1) * parseInt(S, 16) / Math.pow(16,S.length)
        // -> -69.375

That is undertested.  A number string should always have a digit before
its basal separator if any.  Have no non-digit terminator.

function stocktonParseFloat (S, base) {
var A = parseInt(S, base);
if (S = S.split(".")[1])
A += (2*(1/A>0)-1) * parseInt(S, base) / Math.pow(base, S.length);
return A;
}

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

That algorithm has problems, as you can see.
But that is, although easy, not built-in.  Built-on means something like
using unary + rather than valueOf or getTime on a Date Object would be
if those two methods did not exist - an inconspicuous but useful fearure
of the language as specified, generally missing from non-normative
descriptions of the language.

Ok.
 
L

Lasse Reichstein Nielsen

Ry Nohryb said:
....
That's very interesting. Any clues as to why ?

Best guess is that the extra or missing arguments makes it harder
to just pass the arguments on the stack to the function. You need
to either introduce extra undefined values or change where the
function looks for its arguments.

Also, implementations are likely to optimize for the "common case",
which they assume is to call a function with the number of arguments
that it expects. Anything else triggers special code with extra
overhead.

And possibly, local variables can be optimized better, since it's
certain that noone outside the function can see them. Most
implementations still support the (incrdibly stupid) func.arguments
feature where you can access the arguments of the current call to a
function on the function object itself. That alone breaks some
possible optimizations.

/L
 
V

VK

And possibly, local variables can be optimized better, since it's
certain that noone outside the function can see them. Most
implementations still support the (incrdibly stupid) func.arguments
feature where you can access the arguments of the current call to a
function on the function object itself. That alone breaks some
possible optimizations.

I do not agree that the possibility to send any amount of arguments to
a function without being bothered with formal argument IDs is a stupid
feature. IMHO it is very handy. Also you seem reversing the production
mechanics: arguments object is created and filled on function call in
either case, with formal argument names provided or not. *Then* formal
argument names are used to init them with arguments members from
arguments[0] to arguments.length-1
Respectively I would expect arguments usage to be (fractionally)
quicker than formal argument names usage.
 
L

Lasse Reichstein Nielsen

VK said:
I do not agree that the possibility to send any amount of arguments to
a function without being bothered with formal argument IDs is a stupid
feature.

And that's not what I said.

I dislike the implicit "arguments" object way of exposing extra arguments,
but I admit that it serves a purpose. There are different approaches and
some would probably have been better for performance and ease of use.

What I don't see any reasonable use for, and a lot of problems with, is
reading the arguments object off the function object:

function foo() {
bar();
}
function bar() {
alert(foo.arguments[0]);
}
foo("Can't keep me secret");

If it wasn't for that feature, calling a function that doesn't use the
arguments object with more arguments than it actually needs, could just
be done by dropping the extra arguments. Instead, the extra arguments
need to be stored, and the function call needs to adapt them to match
the code of the function, which is optimized for the common case of
getting the parameters that it expects.
IMHO it is very handy. Also you seem reversing the production
mechanics: arguments object is created and filled on function call in
either case, with formal argument names provided or not. *Then* formal
argument names are used to init them with arguments members from
arguments[0] to arguments.length-1

The arguments object doesn't need to be created unless it is actually
used. An optimizing compiler can keep the arguments on the stack and
work on them directly from there, without creating any arguments object.
That is, unless someone actually uses the arguments object. In that
case, you need to alias the arguments and the arguments object, and
all accesses go through an extra layer of indirection (or more).

The design is most likely derived from an early implementation that
did just this, but that's why more efficient implementations have such
a hard time with this language: The specification derives from a
specific implementation strategy, with unnecessary features that
just happened to be easily implemented using that strategy. [1]
Respectively I would expect arguments usage to be (fractionally)
quicker than formal argument names usage.

That's because actual implementations are doing the opposite of what
you expect.

/L
[1] Don't get me started on properties on the RegExp object.
 

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,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top