Ethan Fox
Ethan Fox

Reputation: 169

Higher precision when parsing string to float

This is my first post here so sorry if it drags a little.

I'm assisting in some research for my professor, and I'm having some trouble with precision when I'm parsing some numbers that need to be precise to the 12th decimal point. For example, here is a number that I'm parsing from a string into an integer, before it's parsed:

-82.636097527336

Here is the code I'm using to parse it, which I also found on this site (thanks for that!):

std::basic_string<char> str = prelim[i];
std::stringstream s_str( str );
float val;
s_str >> val;
degrees.push_back(val);

Where 'prelim[i]' is just the current number I'm on, and 'degrees' is my new vector that holds all of the numbers after they've been parsed to a float. My issue is that, after it's parsed and stored in 'degrees', I do an 'std::cout' command comparing both values side-by-side, and shows up like this (old value (string) on the left, new value (float) on the right):

-82.6361

Does anyone have any insight into how I could alleviate this issue and make my numbers more precise? I suppose I could go character by character and use a switch case, but I think that there's an easier way to do it with just a few lines of code.

Again, thank you in advance and any pointers would be appreciated!

(Edited for clarity regarding how I was outputting the value)

Upvotes: 2

Views: 658

Answers (3)

Ruud
Ruud

Reputation: 3261

There are two problems:

  • A 32-bit float does not have enough precision for 14 decimal digits. From a 32-bit float you can get about 7 decimal digits, because it has a 23-bit binary mantissa. A 64-bit float (double) has 52 bits of mantissa, which gives you about 16 decimal digits, just enough.
  • Printing with cout by default prints six decimal digits.

Here is a little program to illustrate the difference:

#include <iomanip>
#include <iostream>
#include <sstream>

int main(int, const char**)
{
  float parsed_float;
  double parsed_double;
  std::stringstream input("-82.636097527336 -82.636097527336");

  input >> parsed_float;
  input >> parsed_double;

  std::cout << "float printed with default precision: "
            << parsed_float << std::endl;

  std::cout << "double printed with default precision: "
            << parsed_double << std::endl;

  std::cout << "float printed with 14 digits precision: "
            << std::setprecision(14) << parsed_float << std::endl;

  std::cout << "double printed with 14 digits precision: "
            << std::setprecision(14) << parsed_double << std::endl;

  return 0;
}

Output:

float printed with default precision: -82.6361
double printed with default precision: -82.6361
float printed with 14 digits precision: -82.636100769043
double printed with 14 digits precision: -82.636097527336

So you need to use a 64-bit float to be able to represent the input, but also remember to print with the desired precision with std::setprecision.

Upvotes: 2

Matt Jordan
Matt Jordan

Reputation: 2181

Change to a double to represent the value more accurately, and use std::setprecision(30) or more to show as much of the internal representation as is available.

Note that the internal storage isn't exact; using an Intel Core i7, I got the following values:

string: -82.636097527336

float:  -82.63610076904296875

double: -82.63609752733600544161163270473480224609

So, as you can see, double correctly represents all of the digits of your original input string, but even so, it isn't quite exact, since there are a few extra digits than in your string.

Upvotes: 2

Baltasarq
Baltasarq

Reputation: 12212

You cannot have precision up to the 12th decimal using a simple float. The intuitive course of action would be to use double or long double... but your are not going to have the precision your need.

The reason is due to the representation of real numbers in memory. You have more information here.

For example. 0.02 is actually stored as 0.01999999...

You should use a dedicated library for arbitrary precision, instead.

Hope this helps.

Upvotes: 0

Related Questions