Prev: Firefox cache issue
Next: FAQ Topic - How do I format a Number as a String with exactly 2 decimal places? (2010-05-27)
From: Ry Nohryb on 28 May 2010 08:06 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 28 May 2010 08:17 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 28 May 2010 08:34 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 28 May 2010 08:46 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 28 May 2010 08:50
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. |