diff --git a/ssf.js b/ssf.js index 607d185..61b1ac9 100644 --- a/ssf.js +++ b/ssf.js @@ -310,7 +310,18 @@ function hashq(str/*:string*/)/*:string*/ { return o; } function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } -function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); } +function dec(val/*:number*/, d/*:number*/)/*:number*/ { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 0; + } + return Math.round((val-Math.floor(val))*Math.pow(10,d)); +} +function carry(val/*:number*/, d/*:number*/)/*:number*/ { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 1; + } + return 0; +} function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ { if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) { @@ -342,7 +353,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string } if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { - return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length); + return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); } if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { diff --git a/ssf.md b/ssf.md index 89916af..3695a90 100644 --- a/ssf.md +++ b/ssf.md @@ -537,7 +537,18 @@ V8 has an annoying habit of deoptimizing round and floor ``` function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } -function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); } +function dec(val/*:number*/, d/*:number*/)/*:number*/ { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 0; + } + return Math.round((val-Math.floor(val))*Math.pow(10,d)); +} +function carry(val/*:number*/, d/*:number*/)/*:number*/ { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 1; + } + return 0; +} function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } ``` @@ -614,7 +625,7 @@ The next few simplifications ignore leading optional sigils (`#`): } if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { - return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length); + return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); } if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); ``` diff --git a/test/comma.tsv b/test/comma.tsv index cc7a484..85ee283 100644 --- a/test/comma.tsv +++ b/test/comma.tsv @@ -1,15 +1,16 @@ -value #.0000,,, #.0000,, #.0000, -1.2345 .0000 .0000 .0012 -12.345 .0000 .0000 .0123 -123.456 .0000 .0001 .1235 -1234 .0000 .0012 1.2340 -12345 .0000 .0123 12.3450 -123456 .0001 .1235 123.4560 -1234567 .0012 1.2346 1234.5670 -12345678 .0123 12.3457 12345.6780 -123456789 .1235 123.4568 123456.7890 -1234567890 1.2346 1234.5679 1234567.8900 -12345678901 12.3457 12345.6789 12345678.9010 -123456789012 123.4568 123456.7890 123456789.0120 -4321 .0000 .0043 4.3210 -4321234 .0043 4.3212 4321.2340 +value #.0000,,, #.0000,, #.0000, #,##0.0 +0.99 .0000 .0000 .0010 1.0 +1.2345 .0000 .0000 .0012 1.2 +12.345 .0000 .0000 .0123 12.3 +123.456 .0000 .0001 .1235 123.5 +1234 .0000 .0012 1.2340 1,234.0 +12345 .0000 .0123 12.3450 12,345.0 +123456 .0001 .1235 123.4560 123,456.0 +1234567 .0012 1.2346 1234.5670 1,234,567.0 +12345678 .0123 12.3457 12345.6780 12,345,678.0 +123456789 .1235 123.4568 123456.7890 123,456,789.0 +1234567890 1.2346 1234.5679 1234567.8900 1,234,567,890.0 +12345678901 12.3457 12345.6789 12345678.9010 12,345,678,901.0 +123456789012 123.4568 123456.7890 123456789.0120 123,456,789,012.0 +4321 .0000 .0043 4.3210 4,321.0 +4321234 .0043 4.3212 4321.2340 4,321,234.0