# Long based Decimals

Long based Decimals

### Introduction

Arduino has floats that are only accurate to about 6-7 digits. When combined with the fact that floats cannot represent certain decimal values well ( like .1 or .3 ) because they are expressed as negative powers of base 2, you may often see error - especially when full value is printed, or the output is truncated instead of rounded.

I have written a class here that basically stores a whole number into a long. Similar to a float, there is even an "exponent" field that says where the decimal point is in the whole number. Unlike a float, operations are done in base 10 (onto a base 2 number). In exchange for the flexibility of true floating point number in the range of possible values, we gain greater precision in the nearer to zero area - the area firmly within the range of the long (-2,147,483,648 to 2,147,483,647). The smaller the left hand side (LHS) of the decimal place is, the more precision is available for the right hand side (RHS) of the decimal.

### Usage

So far, all I have is a really basic class that only handles the construcor and the bare minimum needed for printing.

```#include "longDecimal.h"

void setup() {
Serial.begin(9600);
Serial.println( "BEGIN TEST:");

LongDecimal dec(131,158272);

Serial.print( dec.getLHS() );
Serial.print( '.' );
Serial.println( dec.getRHS() );

LongDecimal dec1(-131,158272);

Serial.print( dec1.getLHS() );
Serial.print( '.' );
Serial.println( dec1.getRHS() );

LongDecimal dec2(12345678,158272);

Serial.print( dec2.getLHS() );
Serial.print( '.' );
Serial.println( dec2.getRHS() );
}

void loop() {}```

#### Output

```BEGIN TEST:
131.1582720
-131.1582720
12345678.15```

### Class

You might be able to figure out what is going on just based on the documentation on the code for the class as it is:

```#include <Arduino.h>

class LongDecimal {
private:
long decimal;              //the left and right side of decimal
unsigned int decimalPlace; //where the decimal is in the above variable

public:
//constructors
LongDecimal( long lhs, long rhs );
LongDecimal( float f );

//type conversions
long getLHS();
long getRHS();
};

LongDecimal::LongDecimal( long lhs, long rhs ) {
decimalPlace = 0;

//shift lhs to the left in the long
long lhsSpace = abs(lhs);
long rhsSpace = 1;

// float the LHS all the way to the left of the long - may not be desirable
while ( 214748364L > lhsSpace ) { // maximum long divided by ten
lhsSpace *= 10L;

decimalPlace++;
rhsSpace *= 10L;
}

// put the LHS into the main decimal variable
decimal = lhs * rhsSpace;

// float the right hand side to align with LHS    //moves right if necessary - losing precision
while ( rhs > rhsSpace ) {
rhs /= 10;
}
//moves left if necessary
while ( rhs * 10L < rhsSpace ) {
rhs *= 10L;
}

// put the RHS into the main decimal variable
// add to the decimal if positive subtract if negative
if ( lhs < 0 ) {
decimal -= rhs;
}
else {
decimal += rhs;
}

}

//shifts decimal to the right until it is just the left hand side of the decimal
long LongDecimal::getLHS() {
long LHS = decimal;
for( int i = 0; i < decimalPlace; i++ ) {
LHS /= 10;
}
return LHS;
}//removes the left hand side of the decimal by subtraction
long LongDecimal::getRHS() {

long LHS = getLHS(); //removes RHS, but is shifted right
//shift back to the left
for( int i = 0; i < decimalPlace; i++ ) {
LHS *= 10;
}

return abs(decimal) - abs(LHS);
}
```
Evan Boldt Sat, 02/16/2013 - 14:58