Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FloatParts.hpp Source File

FloatParts.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/Configuration.hpp>
00008 #include <ArduinoJson/Numbers/FloatTraits.hpp>
00009 #include <ArduinoJson/Polyfills/math.hpp>
00010 
00011 namespace ARDUINOJSON_NAMESPACE {
00012 
00013 template <typename TFloat>
00014 struct FloatParts {
00015   uint32_t integral;
00016   uint32_t decimal;
00017   int16_t exponent;
00018   int8_t decimalPlaces;
00019 
00020   FloatParts(TFloat value) {
00021     uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
00022     decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
00023 
00024     exponent = normalize(value);
00025 
00026     integral = uint32_t(value);
00027     // reduce number of decimal places by the number of integral places
00028     for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
00029       maxDecimalPart /= 10;
00030       decimalPlaces--;
00031     }
00032 
00033     TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
00034 
00035     decimal = uint32_t(remainder);
00036     remainder = remainder - TFloat(decimal);
00037 
00038     // rounding:
00039     // increment by 1 if remainder >= 0.5
00040     decimal += uint32_t(remainder * 2);
00041     if (decimal >= maxDecimalPart) {
00042       decimal = 0;
00043       integral++;
00044       if (exponent && integral >= 10) {
00045         exponent++;
00046         integral = 1;
00047       }
00048     }
00049 
00050     // remove trailing zeros
00051     while (decimal % 10 == 0 && decimalPlaces > 0) {
00052       decimal /= 10;
00053       decimalPlaces--;
00054     }
00055   }
00056 
00057   static int16_t normalize(TFloat& value) {
00058     typedef FloatTraits<TFloat> traits;
00059     int16_t powersOf10 = 0;
00060 
00061     int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
00062     int bit = 1 << index;
00063 
00064     if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
00065       for (; index >= 0; index--) {
00066         if (value >= traits::positiveBinaryPowerOfTen(index)) {
00067           value *= traits::negativeBinaryPowerOfTen(index);
00068           powersOf10 = int16_t(powersOf10 + bit);
00069         }
00070         bit >>= 1;
00071       }
00072     }
00073 
00074     if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
00075       for (; index >= 0; index--) {
00076         if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
00077           value *= traits::positiveBinaryPowerOfTen(index);
00078           powersOf10 = int16_t(powersOf10 - bit);
00079         }
00080         bit >>= 1;
00081       }
00082     }
00083 
00084     return powersOf10;
00085   }
00086 };
00087 }  // namespace ARDUINOJSON_NAMESPACE