From: Ry Nohryb on
On May 28, 1:34 pm, Ry Nohryb wrote:
> On May 27, 11:07 pm, Thomas 'PointedEars' Lahn 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:
> (...)

How about this one ?

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

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

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

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

"-dead.bee".toFP(16).toString(16)
"-dead.bee"

"+bad.c0ffee".toFP(16).toString(16)
"bad.c0ffee"
--
Jorge.
From: Ry Nohryb on
On May 28, 2:06 pm, Ry Nohryb <jo...(a)jorgechamorro.com> wrote:
>
> How about this one ?
>
> 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;
>
> };

D'oh, not yet... :-)

"Pointy.isUgly".toFP(36).toString(36)
--> "pointy.isugkchaor"
--
Jorge.
From: Thomas 'PointedEars' Lahn on
Ry Nohryb wrote:

> Thomas 'PointedEars' Lahn 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)
> --> -2.858407346410207

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);

> 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;
> };

I prefer using regular expressions where possible but only where necessary,
and to avoid callbacks. So my current quick hack looks as follows:

/**
* Parses a string of characters into a Number value. It replaces the
* built-in function in that it supports fractional parts on non-decimal
* representations, and uses the built-in for decimal representations.
*
* @param s : String
* String representation to be parsed
* @param iBase : Number
* Numeric base of the representation, from 2 to 36 inclusive.
* @return number
*/
var parseFloat = jsx.string.parseFloat = (function () {
var origPF = parseFloat;

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

var
i = (s.indexOf(".") != 0 ? parseInt(s, iBase) : 0),
chars = (iBase < 10
? "0-" + String.fromCharCode(47 + iBase)
: "\\d"
+ (iBase > 10
? "a"
+ (iBase > 11
? "-" + String.fromCharCode(86 + iBase)
: "")
: "")),
f = (s.match(new RegExp("\\.([" + chars + "]+)", "i")) || [, "0"])[1],

return i + (i < 0 ? -1 : 1)
* parseInt(f, iBase) / Math.pow(iBase, f.length);
};
}());

As for your misusing arguments as local variables and the resulting
unreadable, unmaintainable, and insecure code, that has been discussed ad
nauseam. Will you ever learn?

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

So you are essentially saying that you managed to produce code garbage,
as usual?

And stop calling me Pointy, Georgina.


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 28, 2:34 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de>
wrote:
> Ry Nohryb wrote:
> > Thomas 'PointedEars' Lahn 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)
> > --> -2.858407346410207
>
> 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);
> (...)

Better, but still not there:

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

pointyParseFloat((-Math.PI).toString(33), 33)
--> -3.121212121212121
--
Jorge.
From: Ry Nohryb on
On May 28, 2:34 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de>
wrote:
> (...)
> I prefer using regular expressions where possible but only where necessary,
> and to avoid callbacks.  So my current quick hack looks as follows:
>
> /**
>  * Parses a string of characters into a Number value.  It replaces the
>  * built-in function in that it supports fractional parts on non-decimal
>  * representations, and uses the built-in for decimal representations.
>  *
>  * @param s : String
>  *   String representation to be parsed
>  * @param iBase : Number
>  *   Numeric base of the representation, from 2 to 36 inclusive.
>  * @return number
>  */
> var parseFloat /*= jsx.string.parseFloat*/ = (function () {
>   var origPF = parseFloat;
>
>   return function (s, iBase) {
>     if (!iBase || iBase == 10)
>     {
>       return origPF(s);
>     }
>
>     var
>       i = (s.indexOf(".") != 0 ? parseInt(s, iBase) : 0),
>       chars = (iBase < 10
>         ? "0-" + String.fromCharCode(47 + iBase)
>         : "\\d"
>           + (iBase > 10
>             ? "a"
>               + (iBase > 11
>                 ? "-" + String.fromCharCode(86 + iBase)
>                 : "")
>             : "")),
>       f = (s.match(new RegExp("\\.([" + chars + "]+)", "i")) || [, "0"])[1],
>
>     return i + (i < 0 ? -1 : 1)
>       * parseInt(f, iBase) / Math.pow(iBase, f.length);
>   };
>
> }());


parseFloat(Math.PI.toString(33), 33)
--> NaN

Cool !
--
Jorge.