1. 程式人生 > >Arduino 權威指南 第二版 第二章 2.3 使用浮點數

Arduino 權威指南 第二版 第二章 2.3 使用浮點數

 在Arduino中,浮點運算的結果是不夠準確的,並且返回的值可以有一個小的近似誤差。出現誤差的原因時浮點僅用32為來儲存一個巨大範圍內的所有值。8位用於小數位置(指數),剩下的24位留給符號和數值,只夠7位有效十進位制數字。     雖然在Arduino中float和double是完全一樣的精度,但是doubles在其他平臺中卻具有更高的精度。因此,當你從另一個平臺中匯入使用float和doubles的程式碼之前,需要檢查是否為你的應用程式提供了足夠的精度。     下面的程式碼顯示瞭如何宣告浮點型變數,表明了比較浮點數時可能會遇到的問題,並演示瞭如何克服這些問題。
  1. /*
  2. * 浮點例子
  3. *本程式初始化浮點值至1.1
  4. *它減少0.1的,直到該值為0
  5. */
  6. float value =1.1;
  7. void setup()
  8. {
  9. Serial.begin(9600); // 開啟串列埠監視器視窗(波特率為9600)
  10. }
  11. void loop()
  12. {
  13. value = value -0.1;// 每迴圈一次減少0.1
  14. if( value ==0)
  15. Serial.println("The value is exactly zero");
  16. elseif(almostEqual(value,0))
  17. {
  18. Serial.print("The value");
  19. Serial.print(value,7);// 列印到7位小數
  20. Serial.println("is almost equal to zero"
    );
  21. }
  22. else
  23. Serial.println(value);
  24. delay(100);
  25. }
  26. // 如果a和b之間的差很小,則返回true
  27. // 把DELTA的值設為能視作相等的最大差值
  28. boolean almostEqual(float a,float b)
  29. {
  30. constfloat DELTA =.00001;// 視作幾乎相等的最大差值
  31. if(a ==0)return fabs(b)<= DELTA;
  32. if(b ==0)return fabs(a)<= DELTA;
  33. return fabs((a-b)/ max(fabs(a),fabs(b)))<= DELTA ;
  34. }
    串列埠監視器的輸出如下圖所示:
 輸出繼續產生負數。     在value為0.1減去0.1後,你可能期望程式碼列印“The value is exactly zero”(數值是精確的零)。但value不會恰好等於零,但會非常接近,無法通過測試:if ( value == 0)。這是因為為了讓浮點數可以覆蓋大的範圍,儲存數值的近似值是唯一有效使用記憶體的方式。
    解決方案:檢查一個變數是否靠近所需的值。     almostEqual函式測試變數value的值是否在所希望的目標0.00001之內,如果成立,則返回true。可接受的範圍由變數DELTA設定,你可以根據需要更改數值。fabs函式(浮點絕對值的縮寫)返回一個浮點變數的絕對值,用來測試給定的引數之間的差值。