Skip to content

Commit

Permalink
Remove fudge factor when computing exponent.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Jun 15, 2015
1 parent 0087f90 commit c83ad05
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 43 deletions.
15 changes: 0 additions & 15 deletions src/btod.js

This file was deleted.

6 changes: 4 additions & 2 deletions src/exponent.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export default function(value) {
return Math.floor(Math.log(value) / Math.LN10 + 1e-12);
import formatDecimal from "./formatDecimal";

export default function(x) {
return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
};
20 changes: 11 additions & 9 deletions src/formatAutoPrefix.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import btod from "./btod";
import formatDecimal from "./formatDecimal";

export var prefixExponent;

export default function(x, p) {
var d = btod(x, p);
var d = formatDecimal(x, p);
if (!d) return x + "";
var i = d.exponent;
var coefficient = d[0],
exponent = d[1],
i = exponent + 1;
if (i >= 24) i -= 24;
else if (i <= -24) d.coefficient = new Array(-22 - i).join("0") + d.coefficient.slice(0, i + 23), i = 1;
else if (i <= -24) coefficient = new Array(-22 - i).join("0") + coefficient.slice(0, i + 23), i = 1;
else i %= 3;
if (!i) i = 3;
else if (i < 0) i += 3;
prefixExponent = Math.max(-24, Math.min(24, Math.floor((d.exponent - 1) / 3) * 3));
return d.coefficient.slice(0, i)
+ (d.coefficient.length > i
? "." + d.coefficient.slice(i)
: new Array(i - d.coefficient.length + 1).join("0"));
prefixExponent = Math.max(-24, Math.min(24, Math.floor(exponent / 3) * 3));
return coefficient.slice(0, i)
+ (coefficient.length > i
? "." + coefficient.slice(i)
: new Array(i - coefficient.length + 1).join("0"));
};
14 changes: 14 additions & 0 deletions src/formatDecimal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimal(1.23) returns ["123", -1].
export default function(x, p) {
if ((i = (x = x.toExponential(p - 1)).indexOf("e")) < 0) return null; // NaN, ±Infinity
var i, coefficient = x.slice(0, i);

// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+x.slice(i + 1)
];
};
18 changes: 10 additions & 8 deletions src/formatRounded.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import btod from "./btod";
import formatDecimal from "./formatDecimal";

export default function(x, p) {
var d = btod(x, p);
var d = formatDecimal(x, p);
if (!d) return x + "";
var i = d.exponent;
var coefficient = d[0],
exponent = d[1],
i = exponent + 1;
return i <= 0
? "0." + new Array(1 - i).join("0") + d.coefficient
: d.coefficient.slice(0, i)
+ (d.coefficient.length > i
? "." + d.coefficient.slice(i)
: new Array(i - d.coefficient.length + 1).join("0"));
? "0." + new Array(1 - i).join("0") + coefficient
: coefficient.slice(0, i)
+ (coefficient.length > i
? "." + coefficient.slice(i)
: new Array(i - coefficient.length + 1).join("0"));
};
18 changes: 10 additions & 8 deletions src/formatRoundedPercentage.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import btod from "./btod";
import formatDecimal from "./formatDecimal";

export default function(x, p) {
var d = btod(x, p);
var d = formatDecimal(x, p);
if (!d) return x + "";
var i = d.exponent + 2;
var coefficient = d[0],
exponent = d[1],
i = exponent + 3;
return i <= 0
? "0." + new Array(1 - i).join("0") + d.coefficient
: d.coefficient.slice(0, i)
+ (d.coefficient.length > i
? "." + d.coefficient.slice(i)
: new Array(i - d.coefficient.length + 1).join("0"));
? "0." + new Array(1 - i).join("0") + coefficient
: coefficient.slice(0, i)
+ (coefficient.length > i
? "." + coefficient.slice(i)
: new Array(i - coefficient.length + 1).join("0"));
};
2 changes: 1 addition & 1 deletion src/precisionPrefix.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import exponent from "./exponent";
import precisionFixed from "./precisionFixed";

export default function(step, value) {
return Math.max(0, Math.floor(exponent(value) / 3) * 3 - exponent(Math.abs(step)));
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
};
46 changes: 46 additions & 0 deletions test/precisionPrefix-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var tape = require("tape"),
format = require("../");

// A generalization from µ to all prefixes:
// test.equal(format.precisionPrefix(1e-6, 1e-6), 0); // 1µ
// test.equal(format.precisionPrefix(1e-6, 1e-7), 0); // 10µ
// test.equal(format.precisionPrefix(1e-6, 1e-8), 0); // 100µ
tape("precisionPrefix(step, value) returns zero if step has the same units as value", function(test) {
for (var i = -24; i <= 24; i += 3) {
for (var j = i; j < i + 3; ++j) {
test.equal(format.precisionPrefix(+("1e" + i), +("1e" + j)), 0);
}
}
test.end();
});

// A generalization from µ to all prefixes:
// test.equal(format.precisionPrefix(1e-9, 1e-6), 3); // 0.001µ
// test.equal(format.precisionPrefix(1e-8, 1e-6), 2); // 0.01µ
// test.equal(format.precisionPrefix(1e-7, 1e-6), 1); // 0.1µ
tape("precisionPrefix(step, value) returns greater than zero if fractional digits are needed", function(test) {
for (var i = -24; i <= 24; i += 3) {
for (var j = i - 4; j < i; ++j) {
test.equal(format.precisionPrefix(+("1e" + j), +("1e" + i)), i - j);
}
}
test.end();
});

tape("precisionPrefix(step, value) returns the expected precision when value is less than one yocto", function(test) {
test.equal(format.precisionPrefix(1e-24, 1e-24), 0); // 1y
test.equal(format.precisionPrefix(1e-25, 1e-25), 1); // 0.1y
test.equal(format.precisionPrefix(1e-26, 1e-26), 2); // 0.01y
test.equal(format.precisionPrefix(1e-27, 1e-27), 3); // 0.001y
test.equal(format.precisionPrefix(1e-28, 1e-28), 4); // 0.0001y
test.end();
});

tape("precisionPrefix(step, value) returns the expected precision when value is greater than than one yotta", function(test) {
test.equal(format.precisionPrefix(1e24, 1e24), 0); // 1Y
test.equal(format.precisionPrefix(1e24, 1e25), 0); // 10Y
test.equal(format.precisionPrefix(1e24, 1e26), 0); // 100Y
test.equal(format.precisionPrefix(1e24, 1e27), 0); // 1000Y
test.equal(format.precisionPrefix(1e23, 1e27), 1); // 1000.0Y
test.end();
});

0 comments on commit c83ad05

Please sign in to comment.