Decimal Places

Hi all,

Im trying to figure out how to get more than 3 decimal places to be inputted into a formula and return a more accurate result too.

i have tried making the variables a float and a double.

i want to be able to input this value "44.64978683" without having to go down too "44.65".

When i put the whole value in i get the image below;

Thanks


double level;
double myValue;
String msg1 = "Enter Frequency (type 0 to exit): ";
String msg2 = "Your Frequency is: ";

void setup()
{
Serial.begin(9600);
}

void loop()
{
Serial.print(msg1);

while (Serial.available() == 0);
{

}
myValue = Serial.parseFloat();
if (myValue == 0.0)
{
Serial.end();
}
else
{
freqConversion();
}
}

void freqConversion()
{
level = (myValue-44.712)/-0.0285493333;
Serial.println(myValue);
Serial.print(msg2);
Serial.println(level);
}

seems there's a problem reading your input.
44.64978683 is entered, but the code reports 1.70

dtostrf() can be used to format FP values

By default print() only displays two decimal places, you can specify the number of decimal places:

Serial.println(level, 4); //will print level with 4 decimal places.

Note that in most arduino's double is implemented as float, and float is limited to 6 to 7 significant digits.

david_2018:
By default print() only displays two decimal places, you can specify the number of decimal places:

Serial.println(level, 4); //will print level with 4 decimal places.

Note that in most arduino's double is implemented as float, and float is limited to 6 to 7 significant digits.

I had tested (level,8), and it had outputted "1.70011425" when i had written "44.62352548"

gcjr:
seems there's a problem reading your input.
44.64978683 is entered, but the code reports 1.70

dtostrf() can be used to format FP values

Does this have to be specific?
e.g. could i use dtostrf(myValue,9,7,outValue) and i would of only inputted a number with 7 decimal places?

yes

gcjr:
yes

Error Message
Arduino: 1.8.10 (Windows 10), Board: "Arduino/Genuino Uno"

C:\Users\jacklythgoe\Documents\Training\Arduino Projects\WORK\ArduinoFreqProject\ArduinoFreqProject.ino: In function 'void setup()':

ArduinoFreqProject:9:31: error: cannot convert 'float' to 'char*' for argument '4' to 'char* dtostrf(double, signed char, unsigned char, char*)'

dtostrf(myValue,9,7,outValue);

^

exit status 1
cannot convert 'float' to 'char*' for argument '4' to 'char* dtostrf(double, signed char, unsigned char, char*)'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

float level;
float myValue;
float outValue;
String msg1 = "Enter Frequency (type 0 to exit): ";
String msg2 = "Your Frequency is: ";

void setup()
{
dtostrf(myValue,9,7,outValue);
Serial.begin(9600);
}

void loop()
{
Serial.print(msg1);

while (Serial.available() == 0);
{

}
myValue = Serial.parseFloat();
if (myValue == 0.0)
{
Serial.end();
}
else
{
freqConversion();
}
}

void freqConversion()
{
level = (myValue-44.712)/-0.0285493333;
Serial.println(myValue,8);
Serial.print(msg2);
Serial.println(level,8);
}

dtostrf formats the value into a c string. it doesn't configure the value with a specific # of digits

you need to define and use a char array, and do a conversion for each new value

char s [20]

      dtostrf (myValue, 9, 7, s);
      Serial.println (s);

gcjr:
dtostrf formats the value into a c string. it doesn't configure the value with a specific # of digits

you need to define and use a char array, and do a conversion for each new value

char s [20]

dtostrf (myValue, 9, 7, s);
     Serial.println (s);

Would you be able to implement this into my code? im not really understanding how this is formatted.

Enter Frequency (type 0 to exit): 1.1737840
Your Frequency is: 1525.02
Enter Frequency (type 0 to exit):
void freqConversion()
{
    char s [20];
    dtostrf (myValue, 9, 7, s);
    Serial.println(s);

    level = (myValue-44.712)/-0.0285493333;
    Serial.print(msg2);
    Serial.println(level);
}

You need to think carefully about precision here .

All those significant figures may well be meaningless in the accuracy of the result .
If the input resolution is to say 4 significant figures then there maybe no point having higher resolution in any of the multiplying/dividing factors . You need to test this out , rather than using up all that computing effort. An integer for example may suffice for your input and all following maths .

For example : “ level = (myValue-44.712)/-0.0285493333”

Chopping off the 3333 from the denominator does not affect the accuracy of the result as your numerator is to less significant figures .

Are you having a problem with the input value being incorrect, or only with the result of the calculation? It may be that Serial.parseFloat() cannot handle the excessively long input number.

Which arduino are you using? There is no double on most models, so 44.62352548 will always get shorted to around 4 decimal places.

david_2018:
Are you having a problem with the input value being incorrect, or only with the result of the calculation? It may be that Serial.parseFloat() cannot handle the excessively long input number.

Which arduino are you using? There is no double on most models, so 44.62352548 will always get shorted to around 4 decimal places.

The input value is wrong, which then makes the result wrong. Do you know anyway i could help the parseFloat? as that may be the problem.
I am using the Arduino Elegoo Uno R3.

jacklythgoee:
The input value is wrong, which then makes the result wrong. Do you know anyway i could help the parseFloat? as that may be the problem.

arduino uses many techniques not common in standard C++

String msg1 = "Enter Frequency (type 0 to exit): ";
String msg2 = "Your Frequency is: ";

char inpBuf [80];
int  inpIdx = 0;

void setup()
{
    Serial.begin(9600);
    Serial.print(msg1);
}

void loop()
{
    while (Serial.available()) {
        if ('\n' == (inpBuf [inpIdx++]  = Serial.read()))  {
            float freq = atof (inpBuf);
            freqConversion (freq);
            inpIdx = 0;
            Serial.print(msg1);
        }
    }
}

void freqConversion(
    float freq )
{
    char s [20];
    dtostrf (freq, 10, 7, s);
    Serial.println(s);

    double level = (freq -44.712)/-0.0285493333;
    Serial.print(msg2);
    Serial.println(level);
}

gcjr:
arduino uses many techniques not common in standard C++

String msg1 = "Enter Frequency (type 0 to exit): ";

String msg2 = "Your Frequency is: ";

char inpBuf [80];
int  inpIdx = 0;

void setup()
{
   Serial.begin(9600);
   Serial.print(msg1);
}

void loop()
{
   while (Serial.available()) {
       if ('\n' == (inpBuf [inpIdx++]  = Serial.read()))  {
           float freq = atof (inpBuf);
           freqConversion (freq);
           inpIdx = 0;
           Serial.print(msg1);
       }
   }
}

void freqConversion(
   float freq )
{
   char s [20];
   dtostrf (freq, 10, 7, s);
   Serial.println(s);

double level = (freq -44.712)/-0.0285493333;
   Serial.print(msg2);
   Serial.println(level);
}

i go to run this code and first message gets displayed, when i go to input a value, nothing is returned to me

i should have said that you need to configure your serial monitor to return Newline. it's the box at the bottom to the left of the bitrate (baud)

gcjr:
i should have said that you need to configure your serial monitor to return Newline. it's the box at the bottom to the left of the bitrate (baud)

I have this code functioning now, thank you very much for that. However is there a way to make the input value exact? the output doesnt have to have any decimal places so i can change that to an int im pretty sure.

try it and find out

String msg1 = "Enter Frequency (type 0 to exit): "; 
String msg2 = "Your Frequency is: ";

A great way to waste nearly 70 bytes of precious RAM. Needs more F() macro.

arduino uses many techniques not common in standard C++

:o

gcjr:
try it and find out

changed level to an int and it had worked. Thanks :slight_smile: