@lead said:
So, starting with the smallest number of decimal places and ending with the smallest number of decimal places is preferable, does that make sense?
Formally, it doesn't make sense.
The ratio for 2 semitones down is 2 ** (-2 / 12)
. 2 is a prime number. Raising any (positive) prime number to a fractional power results in an irrational number, with infinitely many decimal places (without ending up in a repeating sequence).
A rational number times an irrational number must be irrational. So your initial bpm value * the ratio is irrational and has infinitely many decimal places. To say "this one has 3 places" glosses over the real situation.
What you're really doing is rounding this irrational number to an arbitrary number of places. The denominator of the rounded number will be 10 ** num_places
-- thus both the numerator and denominator are integers and the result is rational.
The difference (or quotient, depending how you want to measure it) between bpm * ratio
and the rounded version is an error value.
And the math problem, then, is to minimize the error.
You can see it more clearly if you use a language with double precision floats, e.g., SuperCollider:
f = { |bpm, semitones = -2, places = 3|
var r = 2 ** (semitones / 12); // '.midiratio'
var bpm2 = bpm * r;
var rounded = bpm2.round(10 ** places.neg);
// for easier comparison I'll "absolute-value" the error values
var errorDiff = bpm2 absdif: rounded;
var errorRatio = bpm2 / rounded;
if(errorRatio < 1) { errorRatio = 1 / errorRatio };
[bpm2, errorDiff, errorRatio]
};
f.value(69); // [ 61.472011551683, 1.1551683407163e-05, 1.0000001879178 ]
f.value(59); // [ 52.56302437028, 2.4370280016228e-05, 1.0000004636394 ]
f.value(77); // [ 68.599201296806, 0.00020129680612513, 1.0000029343985 ]
... where, indeed, the error for 77 * r is about an order of magnitude worse.
@jameslo -- "It would be cool if you were asking https://math.stackexchange.com/questions/2438510/can-i-find-the-closest-rational-to-any-given-real-if-i-assume-that-the-denomina "
I think this is exactly what the problem reduces to -- what is the closest rational to x
where the denominator = 1000. (However, the numerical methods in the thread will likely evaluate better with double precision floats. Pd prints 6 digits so it may not be clear what you're seeing.)
Actually something else... if x is the original bpm and y is the adjusted, find x and y where the error is minimized. So far the assumption is that x is an integer, but maybe the error could be even lower if they're both fractions.
hjh