Lost Precision With Integer Math. 😕
lardom
Posts: 1,659
in Propeller 1
4,294,967,295 / 65535 = 65537. There is no remainder. Excellent.
4,294,967,295 * sine 0.7071 = 3,036,971,374.29. This is the return I want.
Using integers, 4,294,967,295 / 65535 = 65537 * 7071 = 463,412,127 / 10,000 = 46,341.2127 Move the decimal four places to the right and then four places to the left.
46,341 * 65535 = 3,036,975,435.
3,036,971,374.29 - 3,036,975,435 = -4,060.71
I want that 0.2127 for precision. I will store the final result in a variable array but I want to know if there is a way to calculate both the left and right side of the decimal point in a single process. Am I missing something?
4,294,967,295 * sine 0.7071 = 3,036,971,374.29. This is the return I want.
Using integers, 4,294,967,295 / 65535 = 65537 * 7071 = 463,412,127 / 10,000 = 46,341.2127 Move the decimal four places to the right and then four places to the left.
46,341 * 65535 = 3,036,975,435.
3,036,971,374.29 - 3,036,975,435 = -4,060.71
I want that 0.2127 for precision. I will store the final result in a variable array but I want to know if there is a way to calculate both the left and right side of the decimal point in a single process. Am I missing something?
Comments
I'm pretty sure TTA is Tracy's initials.
Say the factor is sin(45°) = 0.7071. Pre-multiply that times 2^31 = 2147483648. So 2147483648 * 0.7071 = 1518485687
That is the factor to use with **. As follows:
2147483647 ** 1518485687 * 2 * 2 = 3036971372
That is close to the answer you wanted, which was 3,036,971,374.
The extra factors of 2 come from the business that the P1 treats longs as signed integers, and the trick with ** only works with positive numbers, that is, less than 2^31. But the ** operator normalizes to twice that, 2^32.
If 0.7071 is supposed to be sin(45°) = 0.707106781186548, then the factor is 0.707106781186548 * 2^31 = 1518500250, and the ** estimate is,
2147483647 ** 1518500250 * 2 * 2 = 3037000496
whereas 2^32 * sin(45°) = 3037000499.9760.
I'm going to set aside the thought that I have to design an algorithm based on $FFFF_FFFF and instead concentrate on $8000_0000. I still don't understand what "<<15" does but I realize I first have to figure out how it's connected to "FRQA := 54".
Thank you for explaining "**". I absolutely had no idea how that worked.
I have read your posts for years. Thank you.
As to the frqa := 54, that is the number that is added to the phase accumulator, phsa, on each clock cycle. The phase accumulator has a length of 2^32 = 4294967296. Notice that 4294967296 / 54 = 79536431.407407407407407...
No coincidence, it is so close to 80_000_000, which is the clkfreq in the demo. Adding 54 on each clock cycle takes very close to 1 second to get all the way through the phase accumulator, and that means 1Hz output from the NCO mode counter, and it also means 1Hz sine output from the coupled DUTY mode DAC. It's actually a tiny bit off from 1 Hz, by about 0.6%.
factor / 2^31 = 100000/103479.
and it finds that factor = 2075284501. (rounding up). It stores that factor in DAT eeprom.
Now readings from the scale can subsequently be corrected:
correctedReading := reading * 2 ** 2075284501. (the factor of 2 comes from using 31 bits instead of 32 bits, to avoid negative territory)
Note that you can't do it simply, with correctedReading := reading * 100000 /103479, because that might overflow 32 bits or go negative.
@E801 in the sine table is 46340 * 65535 = 3,036,981,900
3,036,981,900 / 4,294,967,295 = 0.70710245071. Time to celebrate.
You also wrote something that made Phil Pilgrim's "UMath" easier to use, I think. I'm trying to find that post again.