-
Arduino vs Significant Figures: Floating Point Calculations
Herewith, to nail down the reasons why you can’t (or, perhaps, shouldn’t) use Arduino
floatvariables, a small collection of DDS-oid calculations.Remember that
floatanddoublevariable are both IEEE 754 single-precision floating point numbers:Size of float: 4 double: 4The Arduino floating-point formatter gags on some values, although they calculate correctly:
2^24: 16777216.000 printf: ? 2^32: ovf or ovf 2^32: ovf 2^32 / 256: 16777216.000
Don’t add values differing by more than seven orders of magnitude and suspect any results beyond the first half-dozen significant figures:
Oscillator steps: HzPerCt Oscillator: 125000000.00 -25 -> 0.02910382461 -24 -> 0.02910382461 -23 -> 0.02910382461 -22 -> 0.02910382461 -21 -> 0.02910382461 -20 -> 0.02910382747 -19 -> 0.02910382747 -18 -> 0.02910382747 -17 -> 0.02910382747 -16 -> 0.02910382747 -15 -> 0.02910382747 -14 -> 0.02910382747 -13 -> 0.02910382747 -12 -> 0.02910382747 -11 -> 0.02910382747 -10 -> 0.02910382747 -9 -> 0.02910382747 -8 -> 0.02910382747 -7 -> 0.02910382747 -6 -> 0.02910382747 -5 -> 0.02910382747 -4 -> 0.02910383033 -3 -> 0.02910383033 -2 -> 0.02910383033 -1 -> 0.02910383033 +0 -> 0.02910383033
The Arduino source code as a GitHub Gist:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersfloat TwoTo32, TwoTo24; float CtPerHz, HzPerCt; double Double; float Oscillator,Frequency; unsigned long int DeltaPhase; //– Helper routine for printf() int s_putc(char c, FILE *t) { Serial.write(c); } //– Calculate delta phase from output & oscillator uint32_t CalculateDP(float Freq, float Osc) { uint32_t DP; Serial.print("Freq: "); Serial.print(Freq,3); Serial.print(" Osc: "); Serial.print(Osc,3); DP = Freq * TwoTo32 / Osc; printf(" -> DP: %lu = 0x%08lx\n",DP,DP); return DP; } //– Calculate frequency from delta phase & oscillator float CalculateFreq(uint32_t DP, float Osc) { float Freq; Freq = DP * Osc / TwoTo32; printf("DP: %lu = 0x%08lx ",DP,DP); Serial.print(" Osc: "); Serial.print(Osc,3); Serial.print(" -> Freq: "); Serial.println(Freq,3); return Freq; } //—————— void setup() { Serial.begin(115200); fdevopen(&s_putc,0); // set up serial output for printf() Serial.println (F("DDS Numeric Values")); Serial.println (F("Ed Nisley – KE4ZNU – May 2017\n")); printf("Size of float: %u\n",sizeof(TwoTo32)); printf(" double: %u\n",sizeof(Double)); TwoTo24 = pow(2.0,24); Serial.print("2^24: "); Serial.println(TwoTo24,3); printf("printf: %8.8f\n",TwoTo24); TwoTo32 = pow(2,32); Serial.print("2^32: "); Serial.print(TwoTo32,3); Serial.print(" or "); Serial.println(TwoTo32,3); TwoTo32 = 4294967296.0; Serial.print("2^32: "); Serial.println(TwoTo32,0); Serial.print("2^32 / 256: "); Serial.println(TwoTo32 / 256.0,3); Oscillator = 125e6; Serial.print("Oscillator: "); Serial.println(Oscillator,3); Frequency = 10e6; Serial.print("Frequency: "); Serial.println(Frequency,3); HzPerCt = Oscillator / TwoTo32; Serial.print("HzPerCt: "); Serial.println(HzPerCt,9); CtPerHz = TwoTo32 / Oscillator; Serial.print("CtPerHz: "); Serial.println(CtPerHz,9); Frequency = 10e6 + 0.0; DeltaPhase = Frequency * CtPerHz; Serial.print(Frequency,3); printf(": Delta Phase: %lu = %08lx\n",DeltaPhase,DeltaPhase); Frequency = 10e6 + 0.5; DeltaPhase = Frequency * CtPerHz; Serial.print(Frequency,3); printf(": Delta Phase: %lu = %08lx\n",DeltaPhase,DeltaPhase); Frequency = 10e6 + 0.8; DeltaPhase = Frequency * CtPerHz; Serial.print(Frequency,3); printf(": Delta Phase: %lu = %08lx\n",DeltaPhase,DeltaPhase); Frequency = 10e6 + 1.0; DeltaPhase = Frequency * CtPerHz; Serial.print(Frequency,3); printf(": Delta Phase: %lu = %08lx\n",DeltaPhase,DeltaPhase); Serial.println("Oscillator steps: HzPerCt"); Serial.print(" Oscillator: "); Serial.println(Oscillator,2); for (int i=-25; i<=25; i++) { HzPerCt = (Oscillator + i) / TwoTo32; printf(" %+3d -> ",i); Serial.println(HzPerCt,11); } Serial.println("Oscillator tune: CtPerHz "); Serial.print(" Oscillator: "); Serial.println(Oscillator,2); for (int i=-25; i<=25; i++) { CtPerHz = TwoTo32 / (Oscillator + i); printf(" %+3d -> ",i); Serial.println(CtPerHz,11); } // printf("CtPerHz int: %lu = %08lx\n",long(CtPerHz),long(CtPerHz)); } //—————— void loop() {} This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersDDS Numeric Values Ed Nisley – KE4ZNU – May 2017 Size of float: 4 double: 4 2^24: 16777216.000 printf: ? 2^32: ovf or ovf 2^32: ovf 2^32 / 256: 16777216.000 Oscillator: 125000000.000 Frequency: 10000000.000 HzPerCt: 0.029103830 CtPerHz: 34.359737396 10000000.000: Delta Phase: 343597376 = 147ae140 10000000.000: Delta Phase: 343597376 = 147ae140 10000001.000: Delta Phase: 343597408 = 147ae160 10000001.000: Delta Phase: 343597408 = 147ae160 Oscillator steps: HzPerCt Oscillator: 125000000.00 -25 -> 0.02910382461 -24 -> 0.02910382461 -23 -> 0.02910382461 -22 -> 0.02910382461 -21 -> 0.02910382461 -20 -> 0.02910382747 -19 -> 0.02910382747 -18 -> 0.02910382747 -17 -> 0.02910382747 -16 -> 0.02910382747 -15 -> 0.02910382747 -14 -> 0.02910382747 -13 -> 0.02910382747 -12 -> 0.02910382747 -11 -> 0.02910382747 -10 -> 0.02910382747 -9 -> 0.02910382747 -8 -> 0.02910382747 -7 -> 0.02910382747 -6 -> 0.02910382747 -5 -> 0.02910382747 -4 -> 0.02910383033 -3 -> 0.02910383033 -2 -> 0.02910383033 -1 -> 0.02910383033 +0 -> 0.02910383033 +1 -> 0.02910383033 +2 -> 0.02910383033 +3 -> 0.02910383033 +4 -> 0.02910383033 +5 -> 0.02910383224 +6 -> 0.02910383224 +7 -> 0.02910383224 +8 -> 0.02910383224 +9 -> 0.02910383224 +10 -> 0.02910383224 +11 -> 0.02910383224 +12 -> 0.02910383224 +13 -> 0.02910383224 +14 -> 0.02910383224 +15 -> 0.02910383224 +16 -> 0.02910383224 +17 -> 0.02910383224 +18 -> 0.02910383224 +19 -> 0.02910383224 +20 -> 0.02910383224 +21 -> 0.02910383701 +22 -> 0.02910383701 +23 -> 0.02910383701 +24 -> 0.02910383701 +25 -> 0.02910383701 Oscillator tune: CtPerHz Oscillator: 125000000.00 -25 -> 34.35974502563 -24 -> 34.35974502563 -23 -> 34.35974502563 -22 -> 34.35974502563 -21 -> 34.35974502563 -20 -> 34.35974121093 -19 -> 34.35974121093 -18 -> 34.35974121093 -17 -> 34.35974121093 -16 -> 34.35974121093 -15 -> 34.35974121093 -14 -> 34.35974121093 -13 -> 34.35974121093 -12 -> 34.35974121093 -11 -> 34.35974121093 -10 -> 34.35974121093 -9 -> 34.35974121093 -8 -> 34.35974121093 -7 -> 34.35974121093 -6 -> 34.35974121093 -5 -> 34.35974121093 -4 -> 34.35973739624 -3 -> 34.35973739624 -2 -> 34.35973739624 -1 -> 34.35973739624 +0 -> 34.35973739624 +1 -> 34.35973739624 +2 -> 34.35973739624 +3 -> 34.35973739624 +4 -> 34.35973739624 +5 -> 34.35973739624 +6 -> 34.35973739624 +7 -> 34.35973739624 +8 -> 34.35973739624 +9 -> 34.35973739624 +10 -> 34.35973739624 +11 -> 34.35973739624 +12 -> 34.35973358154 +13 -> 34.35973358154 +14 -> 34.35973358154 +15 -> 34.35973358154 +16 -> 34.35973358154 +17 -> 34.35973358154 +18 -> 34.35973358154 +19 -> 34.35973358154 +20 -> 34.35973358154 +21 -> 34.35973358154 +22 -> 34.35973358154 +23 -> 34.35973358154 +24 -> 34.35973358154 +25 -> 34.35973358154