fastTrig_optimize.ino - some points
brewmanz opened this issue · comments
in float getError(int i)
for (float f = i - 1; f < i + 1; f += 0.0001)
will work better usingint ii
as loop counter from -10000 to +10000 andf = i + ii * 0.00001;
. Wheni
is at 84, the error difference between expected and actual of 84.0001 and 84.0002 is 'not trivial'. I'm too lazy to calculate it exactly, but floats are accurate to 24 bits (23 stored; 1 implicit) which is 1 in 16,777,216 i.e. potential rounding differences of c.0.000005. That might not seem much, but adding it 10,000 times gives a potential error of 0.05 - that's 500 clicks of 0.0001. Okay, that's extremely unlikely (drifting 50 clicks wouldn't surprise me), but there's no need to throw away accuracy.- For some reason, your loop includes
i-1
but excludesi+1
. This seems an oversight to me; IMO it should be symmetrical. error += abs(sin(f / 180 * PI) - isin(f));
When tracking deviation errors, it's usual to use Least Squares i.e. it's better to have two errors of 2 than one of 3.
in int optimize()
for (int j = -1; j < 1; j++)
+if (j == 0) continue;
this loop only gets actioned forj = -1
. I don't think that this is intended. Also theif (j == 0) continue;
can be removed if you usefor (int j = -1; j <= 1; j+=2)
in void test_isin_error_1(bool show)
- I notice some
delay(10);
and can't work out why they're there. To ensure theSerial.print
stuff has finished, useSerial.flush();
although I don't see any timing that might require that. z += y;
Again, I would use a Least Squares rather than simple sum of errors. Actually I would track both sum-of-error and sum-of-error-squared and calculate/display Std Dev.
in float getError(int i)
- float loop, I know the potential problems with float loops, for the purpose of this test the values are still equidistant enough. In fact I considered to use 2000 random numbers in the interval, but that could cluster so that could create substantial bias.
- excluding i+1 is because with the next 'degree' it will be tested. If I would include it it would have double weight.
- deviation, this was easier to program and as the sin function is monotone continuous in the interval the linear interpolation in every interval is also continuous. Therefor no sudden peaks. Feel free to do a testrun to see if squared error would generate a different lookup table. And yes I already found that the step size / number of test points affect the table. This difference I saw was only 1 so a diff of 1 in 65535 which is at the edge of the accuracy that is feasible with 16 bit.
in int optimize()
- for (j = -1 to +1) that is historical grown, in a first version I had j from -5 to 5 and had to skip 0. but learned quickly that that was overkill while using quite some time.
- Good catch that +1 is missed, will fix that
in void test_isin_error_1(bool show)
- delay(10) indeed to be sure data has been printed. As printing over serial is interrupt based a few of these interrupts may occur during the measurement. 10 millis delay is enough to flush 100 chars so it works well. Serial.flush() would also be good, maybe even better to understand the purpose.
- deviation discussed above.
Got a new run of optimize doing -2 ..+2
current table
test_isin_error_1
ISIN 0-3600 calls:
max error: 0.00012007
avg error: 0.00002303
1145, 2289, 3435, 4572, 5716, 6853, 7989, 9125, 10255, 11385,
12508, 13631, 14745, 15859, 16963, 18067, 19165, 20253, 21342, 22417,
23489, 24553, 25610, 26659, 27703, 28731, 29755, 30773, 31777, 32772,
33756, 34734, 35697, 36649, 37594, 38523, 39445, 40350, 41247, 42131,
42998, 43856, 44701, 45528, 46344, 47147, 47931, 48708, 49461, 50205,
50933, 51646, 52342, 53022, 53686, 54334, 54969, 55579, 56180, 56760,
57322, 57866, 58394, 58908, 59399, 59871, 60327, 60768, 61184, 61584,
61969, 62330, 62677, 63000, 63304, 63593, 63858, 64108, 64334, 64545,
64731, 64903, 65049, 65177, 65289, 65377, 65449, 65501, 65527, 65535
test_isin_error_1
ISIN 0-3600 calls:
max error: 0.00010264
avg error: 0.00002059
so better, will be included next version
Thanx