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 @@ if (value < 0) value *= -1; if (precision) value = d3.round(value, d3_format_precision(value, precision)); 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]; }; ... ...
This diff is collapsed.
 ... ... @@ -10,7 +10,7 @@ d3.formatPrefix = function(value, precision) { if (value < 0) value *= -1; if (precision) value = d3.round(value, d3_format_precision(value, precision)); 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]; }; ... ...
 ... ... @@ -95,7 +95,7 @@ suite.addBatch({ assert.strictEqual(f(145999999.999999347), "146M"); assert.strictEqual(f(1e26), "100Y"); assert.strictEqual(f(.000001), "1.00µ"); assert.strictEqual(f(.009995), "0.0100"); assert.strictEqual(f(.009995), "10.0m"); var f = format(".4s"); assert.strictEqual(f(999.5), "999.5"); assert.strictEqual(f(999500), "999.5k"); ... ... @@ -115,12 +115,20 @@ suite.addBatch({ assert.strictEqual(f(145999999.999999347), "\$146M"); assert.strictEqual(f(1e26), "\$100Y"); assert.strictEqual(f(.000001), "\$1.00µ"); assert.strictEqual(f(.009995), "\$0.0100"); assert.strictEqual(f(.009995), "\$10.0m"); var f = format("\$.4s"); assert.strictEqual(f(999.5), "\$999.5"); assert.strictEqual(f(999500), "\$999.5k"); 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) { var f = format("\$"); assert.strictEqual(f(0), "\$0"); ... ...
 ... ... @@ -10,29 +10,29 @@ suite.addBatch({ "determines the appropriate prefix for small numbers": function(prefix) { assert.equal(prefix(0).symbol, ""); assert.equal(prefix(1e-00).symbol, ""); assert.equal(prefix(1e-01).symbol, ""); assert.equal(prefix(1e-02).symbol, ""); assert.equal(prefix(1e-01).symbol, "m"); assert.equal(prefix(1e-02).symbol, "m"); assert.equal(prefix(1e-03).symbol, "m"); assert.equal(prefix(1e-04).symbol, "m"); assert.equal(prefix(1e-05).symbol, "m"); assert.equal(prefix(1e-04).symbol, "µ"); assert.equal(prefix(1e-05).symbol, "µ"); assert.equal(prefix(1e-06).symbol, "µ"); assert.equal(prefix(1e-07).symbol, "µ"); assert.equal(prefix(1e-08).symbol, "µ"); assert.equal(prefix(1e-07).symbol, "n"); assert.equal(prefix(1e-08).symbol, "n"); assert.equal(prefix(1e-09).symbol, "n"); assert.equal(prefix(1e-10).symbol, "n"); assert.equal(prefix(1e-11).symbol, "n"); assert.equal(prefix(1e-10).symbol, "p"); assert.equal(prefix(1e-11).symbol, "p"); assert.equal(prefix(1e-12).symbol, "p"); assert.equal(prefix(1e-13).symbol, "p"); assert.equal(prefix(1e-14).symbol, "p"); assert.equal(prefix(1e-13).symbol, "f"); assert.equal(prefix(1e-14).symbol, "f"); assert.equal(prefix(1e-15).symbol, "f"); assert.equal(prefix(1e-16).symbol, "f"); assert.equal(prefix(1e-17).symbol, "f"); assert.equal(prefix(1e-16).symbol, "a"); assert.equal(prefix(1e-17).symbol, "a"); assert.equal(prefix(1e-18).symbol, "a"); assert.equal(prefix(1e-19).symbol, "a"); assert.equal(prefix(1e-20).symbol, "a"); assert.equal(prefix(1e-19).symbol, "z"); assert.equal(prefix(1e-20).symbol, "z"); assert.equal(prefix(1e-21).symbol, "z"); assert.equal(prefix(1e-22).symbol, "z"); assert.equal(prefix(1e-23).symbol, "z"); assert.equal(prefix(1e-22).symbol, "y"); assert.equal(prefix(1e-23).symbol, "y"); assert.equal(prefix(1e-24).symbol, "y"); assert.equal(prefix(1e-25).symbol, "y"); assert.equal(prefix(1e-26).symbol, "y"); ... ... @@ -93,18 +93,18 @@ suite.addBatch({ assert.equal(prefix(-1e27).symbol, "Y"); }, "considers the effect of rounding based on precision": function(prefix) { assert.equal(prefix(999.5000000, 4).symbol, ""); assert.equal(prefix(999.5000000, 3).symbol, "k"); assert.equal(prefix(995.0000000, 3).symbol, ""); assert.equal(prefix(995.0000000, 2).symbol, "k"); assert.equal(prefix(950.0000000, 2).symbol, ""); assert.equal(prefix(950.0000000, 1).symbol, "k"); assert.equal(prefix(0.000009995, 4).symbol, "µ"); assert.equal(prefix(0.000009995, 3).symbol, "m"); assert.equal(prefix(0.000009950, 3).symbol, "µ"); assert.equal(prefix(0.000009950, 2).symbol, "m"); assert.equal(prefix(0.000009500, 2).symbol, "µ"); assert.equal(prefix(0.000009500, 1).symbol, "m"); assert.equal(prefix(999.50000, 4).symbol, ""); assert.equal(prefix(999.50000, 3).symbol, "k"); assert.equal(prefix(995.00000, 3).symbol, ""); assert.equal(prefix(995.00000, 2).symbol, "k"); assert.equal(prefix(950.00000, 2).symbol, ""); assert.equal(prefix(950.00000, 1).symbol, "k"); assert.equal(prefix(0.0009995, 4).symbol, "µ"); assert.equal(prefix(0.0009995, 3).symbol, "m"); assert.equal(prefix(0.0009950, 3).symbol, "µ"); assert.equal(prefix(0.0009950, 2).symbol, "m"); assert.equal(prefix(0.0009500, 2).symbol, "µ"); assert.equal(prefix(0.0009500, 1).symbol, "m"); } } }); ... ...
 ... ... @@ -225,13 +225,10 @@ suite.addBatch({ 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, ".1s")), ["0k", "100k", "200k", "300k", "400k", "500k", "600k", "700k", "800k", "900k", "1000k"]); 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, ".-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]); 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, ".2s")), ["0µ", "10µ", "20µ", "30µ", "40µ", "50µ", "60µ", "70µ", "80µ", "90µ", "100µ"]); assert.deepEqual(x.ticks(10).map(x.tickFormat(10, "s")), ["0µ", "10µ", "20µ", "30µ", "40µ", "50µ", "60µ", "70µ", "80µ", "90µ", "100µ"]); }, "if count is not specified, defaults to 10": function(d3) { 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!