Commit 621558c2 authored by Mike Bostock's avatar Mike Bostock
Browse files

Consistent SI-prefix for small numbers.

For reasons that I can’t recall, the SI-prefix behavior was different for small
numbers (between -1 and 1) than it was for large numbers. This commit enforces
consistent behavior, so that the coefficient is always in the range [1, 1000),
like in engineering notation.

For example, the old d3.format("s") would display 0.01 as "0.01", whereas the
new behavior displays it as "10m".
parent 91531cf7
...@@ -2116,7 +2116,7 @@ ...@@ -2116,7 +2116,7 @@
if (value < 0) value *= -1; if (value < 0) value *= -1;
if (precision) value = d3.round(value, d3_format_precision(value, precision)); if (precision) value = d3.round(value, d3_format_precision(value, precision));
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
} }
return d3_formatPrefixes[8 + i / 3]; return d3_formatPrefixes[8 + i / 3];
}; };
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ d3.formatPrefix = function(value, precision) { ...@@ -10,7 +10,7 @@ d3.formatPrefix = function(value, precision) {
if (value < 0) value *= -1; if (value < 0) value *= -1;
if (precision) value = d3.round(value, d3_format_precision(value, precision)); if (precision) value = d3.round(value, d3_format_precision(value, precision));
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
} }
return d3_formatPrefixes[8 + i / 3]; return d3_formatPrefixes[8 + i / 3];
}; };
......
...@@ -95,7 +95,7 @@ suite.addBatch({ ...@@ -95,7 +95,7 @@ suite.addBatch({
assert.strictEqual(f(145999999.999999347), "146M"); assert.strictEqual(f(145999999.999999347), "146M");
assert.strictEqual(f(1e26), "100Y"); assert.strictEqual(f(1e26), "100Y");
assert.strictEqual(f(.000001), "1.00µ"); assert.strictEqual(f(.000001), "1.00µ");
assert.strictEqual(f(.009995), "0.0100"); assert.strictEqual(f(.009995), "10.0m");
var f = format(".4s"); var f = format(".4s");
assert.strictEqual(f(999.5), "999.5"); assert.strictEqual(f(999.5), "999.5");
assert.strictEqual(f(999500), "999.5k"); assert.strictEqual(f(999500), "999.5k");
...@@ -115,12 +115,20 @@ suite.addBatch({ ...@@ -115,12 +115,20 @@ suite.addBatch({
assert.strictEqual(f(145999999.999999347), "$146M"); assert.strictEqual(f(145999999.999999347), "$146M");
assert.strictEqual(f(1e26), "$100Y"); assert.strictEqual(f(1e26), "$100Y");
assert.strictEqual(f(.000001), "$1.00µ"); assert.strictEqual(f(.000001), "$1.00µ");
assert.strictEqual(f(.009995), "$0.0100"); assert.strictEqual(f(.009995), "$10.0m");
var f = format("$.4s"); var f = format("$.4s");
assert.strictEqual(f(999.5), "$999.5"); assert.strictEqual(f(999.5), "$999.5");
assert.strictEqual(f(999500), "$999.5k"); assert.strictEqual(f(999500), "$999.5k");
assert.strictEqual(f(.009995), "$9.995m"); assert.strictEqual(f(.009995), "$9.995m");
}, },
"SI prefix notation precision is consistent for small and large numbers": function(format) {
assert.deepEqual(
[ 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e-0, 1e1, 1e2, 1e3, 1e4, 1e5].map(format("s")),
[ '10µ', '100µ', '1m', '10m', '100m', '1', '10', '100', '1k', '10k', '100k']);
assert.deepEqual(
[ 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e-0, 1e1, 1e2, 1e3, 1e4, 1e5].map(format(".4s")),
['10.00µ', '100.0µ', '1.000m', '10.00m', '100.0m', '1.000', '10.00', '100.0', '1.000k', '10.00k', '100.0k']);
},
"can output a currency": function(format) { "can output a currency": function(format) {
var f = format("$"); var f = format("$");
assert.strictEqual(f(0), "$0"); assert.strictEqual(f(0), "$0");
......
...@@ -10,29 +10,29 @@ suite.addBatch({ ...@@ -10,29 +10,29 @@ suite.addBatch({
"determines the appropriate prefix for small numbers": function(prefix) { "determines the appropriate prefix for small numbers": function(prefix) {
assert.equal(prefix(0).symbol, ""); assert.equal(prefix(0).symbol, "");
assert.equal(prefix(1e-00).symbol, ""); assert.equal(prefix(1e-00).symbol, "");
assert.equal(prefix(1e-01).symbol, ""); assert.equal(prefix(1e-01).symbol, "m");
assert.equal(prefix(1e-02).symbol, ""); assert.equal(prefix(1e-02).symbol, "m");
assert.equal(prefix(1e-03).symbol, "m"); assert.equal(prefix(1e-03).symbol, "m");
assert.equal(prefix(1e-04).symbol, "m"); assert.equal(prefix(1e-04).symbol, "µ");
assert.equal(prefix(1e-05).symbol, "m"); assert.equal(prefix(1e-05).symbol, "µ");
assert.equal(prefix(1e-06).symbol, "µ"); assert.equal(prefix(1e-06).symbol, "µ");
assert.equal(prefix(1e-07).symbol, "µ"); assert.equal(prefix(1e-07).symbol, "n");
assert.equal(prefix(1e-08).symbol, "µ"); assert.equal(prefix(1e-08).symbol, "n");
assert.equal(prefix(1e-09).symbol, "n"); assert.equal(prefix(1e-09).symbol, "n");
assert.equal(prefix(1e-10).symbol, "n"); assert.equal(prefix(1e-10).symbol, "p");
assert.equal(prefix(1e-11).symbol, "n"); assert.equal(prefix(1e-11).symbol, "p");
assert.equal(prefix(1e-12).symbol, "p"); assert.equal(prefix(1e-12).symbol, "p");
assert.equal(prefix(1e-13).symbol, "p"); assert.equal(prefix(1e-13).symbol, "f");
assert.equal(prefix(1e-14).symbol, "p"); assert.equal(prefix(1e-14).symbol, "f");
assert.equal(prefix(1e-15).symbol, "f"); assert.equal(prefix(1e-15).symbol, "f");
assert.equal(prefix(1e-16).symbol, "f"); assert.equal(prefix(1e-16).symbol, "a");
assert.equal(prefix(1e-17).symbol, "f"); assert.equal(prefix(1e-17).symbol, "a");
assert.equal(prefix(1e-18).symbol, "a"); assert.equal(prefix(1e-18).symbol, "a");
assert.equal(prefix(1e-19).symbol, "a"); assert.equal(prefix(1e-19).symbol, "z");
assert.equal(prefix(1e-20).symbol, "a"); assert.equal(prefix(1e-20).symbol, "z");
assert.equal(prefix(1e-21).symbol, "z"); assert.equal(prefix(1e-21).symbol, "z");
assert.equal(prefix(1e-22).symbol, "z"); assert.equal(prefix(1e-22).symbol, "y");
assert.equal(prefix(1e-23).symbol, "z"); assert.equal(prefix(1e-23).symbol, "y");
assert.equal(prefix(1e-24).symbol, "y"); assert.equal(prefix(1e-24).symbol, "y");
assert.equal(prefix(1e-25).symbol, "y"); assert.equal(prefix(1e-25).symbol, "y");
assert.equal(prefix(1e-26).symbol, "y"); assert.equal(prefix(1e-26).symbol, "y");
...@@ -93,18 +93,18 @@ suite.addBatch({ ...@@ -93,18 +93,18 @@ suite.addBatch({
assert.equal(prefix(-1e27).symbol, "Y"); assert.equal(prefix(-1e27).symbol, "Y");
}, },
"considers the effect of rounding based on precision": function(prefix) { "considers the effect of rounding based on precision": function(prefix) {
assert.equal(prefix(999.5000000, 4).symbol, ""); assert.equal(prefix(999.50000, 4).symbol, "");
assert.equal(prefix(999.5000000, 3).symbol, "k"); assert.equal(prefix(999.50000, 3).symbol, "k");
assert.equal(prefix(995.0000000, 3).symbol, ""); assert.equal(prefix(995.00000, 3).symbol, "");
assert.equal(prefix(995.0000000, 2).symbol, "k"); assert.equal(prefix(995.00000, 2).symbol, "k");
assert.equal(prefix(950.0000000, 2).symbol, ""); assert.equal(prefix(950.00000, 2).symbol, "");
assert.equal(prefix(950.0000000, 1).symbol, "k"); assert.equal(prefix(950.00000, 1).symbol, "k");
assert.equal(prefix(0.000009995, 4).symbol, "µ"); assert.equal(prefix(0.0009995, 4).symbol, "µ");
assert.equal(prefix(0.000009995, 3).symbol, "m"); assert.equal(prefix(0.0009995, 3).symbol, "m");
assert.equal(prefix(0.000009950, 3).symbol, "µ"); assert.equal(prefix(0.0009950, 3).symbol, "µ");
assert.equal(prefix(0.000009950, 2).symbol, "m"); assert.equal(prefix(0.0009950, 2).symbol, "m");
assert.equal(prefix(0.000009500, 2).symbol, "µ"); assert.equal(prefix(0.0009500, 2).symbol, "µ");
assert.equal(prefix(0.000009500, 1).symbol, "m"); assert.equal(prefix(0.0009500, 1).symbol, "m");
} }
} }
}); });
......
...@@ -225,13 +225,10 @@ suite.addBatch({ ...@@ -225,13 +225,10 @@ suite.addBatch({
var x = d3.scale.linear().domain([0, 1e6]); var x = d3.scale.linear().domain([0, 1e6]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0.0M", "0.1M", "0.2M", "0.3M", "0.4M", "0.5M", "0.6M", "0.7M", "0.8M", "0.9M", "1.0M"]); assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0.0M", "0.1M", "0.2M", "0.3M", "0.4M", "0.5M", "0.6M", "0.7M", "0.8M", "0.9M", "1.0M"]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "+$s")), ["+$0.0M", "+$0.1M", "+$0.2M", "+$0.3M", "+$0.4M", "+$0.5M", "+$0.6M", "+$0.7M", "+$0.8M", "+$0.9M", "+$1.0M"]); assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "+$s")), ["+$0.0M", "+$0.1M", "+$0.2M", "+$0.3M", "+$0.4M", "+$0.5M", "+$0.6M", "+$0.7M", "+$0.8M", "+$0.9M", "+$1.0M"]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, ".1s")), ["0k", "100k", "200k", "300k", "400k", "500k", "600k", "700k", "800k", "900k", "1000k"]);
var x = d3.scale.linear().domain([0, 1e5]); var x = d3.scale.linear().domain([0, 1e5]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0k", "10k", "20k", "30k", "40k", "50k", "60k", "70k", "80k", "90k", "100k"]); assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0k", "10k", "20k", "30k", "40k", "50k", "60k", "70k", "80k", "90k", "100k"]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, ".-1s")), ["0.00M", "0.01M", "0.02M", "0.03M", "0.04M", "0.05M", "0.06M", "0.07M", "0.08M", "0.09M", "0.10M"]);
var x = d3.scale.linear().domain([0, 1e-4]); var x = d3.scale.linear().domain([0, 1e-4]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0.00m", "0.01m", "0.02m", "0.03m", "0.04m", "0.05m", "0.06m", "0.07m", "0.08m", "0.09m", "0.10m"]); assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["", "10µ", "20µ", "30µ", "40µ", "50µ", "60µ", "70µ", "80µ", "90µ", "100µ"]);
assert.deepEqual(x.ticks(10).map(x.tickFormat(10, ".2s")), ["", "10µ", "20µ", "30µ", "40µ", "50µ", "60µ", "70µ", "80µ", "90µ", "100µ"]);
}, },
"if count is not specified, defaults to 10": function(d3) { "if count is not specified, defaults to 10": function(d3) {
var x = d3.scale.linear(); var x = d3.scale.linear();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment