These are some tests to check behavior of the d3 range() method when it is used with fractional step sizes.
https://github.com/d3/d3-arrays has the candidate versions for a new release d3. The range() function below is copied over from there.
These are some tests to check behavior of the d3 range() method when it is used with fractional step sizes.
https://github.com/d3/d3-arrays has the candidate versions for a new release d3. The range() function below is copied over from there.
<html> | |
<body> | |
<p> | |
number of unexpected range(0, 1, step) lengths for steps 1/n with n = 1 to | |
<span id='result1'> </span>. | |
</p> | |
<p>with workaround</p> | |
<p> | |
number of unexpected range(0, 1-eps, step) lengths for eps=1e<sup>-17</sup> and steps 1/n with n = 1 to | |
<span id='result2'> </span>. | |
</p> | |
<p> | |
number of unexpected range(0, (1-eps)*max, step) lengths for steps max/n and max = 2<sup>m</sup> with n = 1 to | |
<span id='result3'> </span>. | |
</p> | |
<p> | |
number of unexpected range(offset, offset + (1-eps)*max, step) lengths for steps max/n, max = 2<sup>m</sup> and offset = 3<sup>m</sup> with n = 1 to | |
<span id='result4'> </span>. | |
</p> | |
number of unexpected range(0, 1-eps, step) lengths for eps=1e<sup>-16</sup> and steps 1/n with n = 1 to | |
<span id='result2b'> </span>. | |
</p> | |
<p> | |
number of unexpected range(0, (1-eps)*max, step) lengths for steps max/n and max = 2<sup>m</sup> with n = 1 to | |
<span id='result3b'> </span>. | |
</p> | |
<p> | |
number of unexpected range(offset, offset + (1-eps)*max, step) lengths for steps max/n, max = 2<sup>m</sup> and offset = 3<sup>m</sup> with n = 1 to | |
<span id='result4b'> </span>. | |
</p> | |
<p> | |
number of unexpected range((1-eps)*offset, (1-eps)*(offset + max), step) lengths for steps max/n, max = 2<sup>m</sup> and offset = 3<sup>m</sup> with n = 1 to | |
<span id='result4c'> </span>. | |
</p> | |
<p> | |
number of unexpected range((1-eps)*offset, (1-eps)*(offset + max), step) lengths for eps=1e<sup>-10</sup> and steps max/n, max = 2<sup>m</sup> and offset = 3<sup>m</sup> with n = 1 to | |
<span id='result4d'> </span>. | |
</p> | |
<script> | |
//this is the new range function | |
function range(start, stop, step) { | |
if ((n = arguments.length) < 3) { | |
step = 1; | |
if (n < 2) { | |
stop = start; | |
start = 0; | |
} | |
} | |
var i = -1, | |
n = Math.max(0, Math.ceil((stop - start) / step)) | 0, | |
k = scale(Math.abs(step)), | |
range = new Array(n); | |
start *= k; | |
step *= k; | |
while (++i < n) { | |
range[i] = (start + i * step) / k; | |
} | |
return range; | |
}; | |
function scale(x) { | |
var k = 1; | |
while (x * k % 1) k *= 10; | |
return k; | |
}; | |
//test | |
function collect_mismatches(max_d, eps, eps2, offset, max) { | |
var mismatches = []; | |
var max = max; | |
range(1, max_d).forEach(function(d) { | |
if (range(offset * (1-eps2), offset * (1-eps2) + max * (1-eps), max/d).length !== d) | |
{mismatches.push([offset, max, d]);} | |
}); | |
return mismatches; | |
}; | |
function mismatches_thru_domains(max_d, eps, eps2, minscale, max_e) { | |
var collected = []; | |
range(0, max_e).forEach(function(e) { | |
var max = Math.pow(2, e); | |
var min = Math.pow(3, e) * minscale; | |
collected = collected.concat(collect_mismatches(max_d, eps, eps2, min, max)); | |
}); | |
return collected; | |
}; | |
var max_denominator = 1000; | |
var max_expo = 64; | |
var r1 = collect_mismatches(max_denominator, 0, 0, 0, 1).length; | |
var r2 = collect_mismatches(max_denominator, 1e-17, 0, 0, 1).length; | |
var r3 = mismatches_thru_domains(max_denominator, 1e-17, 0, 0, max_expo).length; | |
var r4 = mismatches_thru_domains(max_denominator, 1e-17, 0, 1, max_expo).length; | |
var r2b = collect_mismatches(max_denominator, 1e-16, 0, 0, 1).length; | |
var r3b = mismatches_thru_domains(max_denominator, 1e-16, 0, 0, max_expo).length; | |
var ar4b = mismatches_thru_domains(max_denominator, 1e-16, 0 , 1, max_expo); | |
var ar4c = mismatches_thru_domains(max_denominator, 1e-16, 1e-16, 1, max_expo); | |
var ar4d = mismatches_thru_domains(max_denominator, 1e-10, 1e-10, 1, max_expo); | |
document.getElementById('result1').textContent = max_denominator + " : " + r1; | |
document.getElementById('result2').textContent = max_denominator + " : " + r2; | |
document.getElementById('result3').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + r3; | |
document.getElementById('result4').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + r4; | |
document.getElementById('result2b').textContent = max_denominator + " : " + r2b; | |
document.getElementById('result3b').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + r3b; | |
document.getElementById('result4b').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + ar4b.length + " ; first: " + ar4b[0]; | |
document.getElementById('result4c').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + ar4c.length + " ; first: " + ar4c[0]; | |
document.getElementById('result4d').textContent = max_denominator + " and m = 0 to " + max_expo + " : " + ar4d.length + " ; first: " + ar4d[0]; | |
</script> | |
</body> | |
</html> |
dat shows. |