2

I have a string which has the value "496934.079" . I use boost::lexical_cast () to convert this into a double variable (named pVar).

However the value stored in pVar after conversion is "496934" not "496934.079". The digits after the decimal points are missing. I have read about std::setprecision() for writing the double value with needed precision in the output window here. But it only displays value with the given precision and it does not saves it in the variable with the given prescision.

But I want to store the double value exactly as it is in the string variable str so that the value in pVar is "496934.079". How can I store the value in the variable with same precision as in the input string so that I can use the variable for further processing?

My code snippet is:

int func()
{
    string str = "496934.079";
    double pVar = boost::lexical_cast<double> (str);
    cout << pVar << endl;
    return 0;
}

EDIT: This conversion from string to float is part of the code I am developing which parses values from a text file line-by-line and writes them into another file (.pcd format). I am adding the entire code I use for this conversion for reference.

int txt2pcd()
{
    ifstream is("input_text_file.txt");                                         //read input text file
    string str;
    using namespace boost::algorithm;
    pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
    while(getline(is, str))                                                     //parsing the text file contents line-by-line
    {   
        std::string s = str.c_str();
        std::vector<std::string> result;            
        std::istringstream iss(s);
        for(std::string s; iss >> s; )
            result.push_back(s);

        pcl::PointXYZ point;

        point.x = boost::lexical_cast<double> (result[0]);                      //string to float conversion for adding the X coordinate of the point
        point.y = boost::lexical_cast<double> (result[1]);                      //string to float conversion for adding the Y coordinate of the point
        point.z = boost::lexical_cast<double> (result[2]);                      //string to float conversion for adding the Z coordinate of the point

        point_cloud_ptr->points.push_back (point);
        point_cloud_ptr->width = (int) point_cloud_ptr->points.size ();
        point_cloud_ptr->height = 1;            
    }   
    pcl::io::savePCDFile ("output_pcd_file.pcd", *point_cloud_ptr, false);    //this is where the converted float values are stored (with digits altered after decimal point when compared to text file)
    return 0;
}

Below are few sample few lines from the text file and the corresponding lines from the converted '.pcd' file.

In text file:

496934.999 5419547.239 265.179

496933.981 5419542.579 263.819

496934.891 5419545.399 264.849

496934.939 5419546.329 265.111

496934.829 5419544.489 264.781

In '.pcd' file (corresponding values resulting from boost::lexical_cast ())

496935 5419547 265.17899

496933.97 5419542.5 263.819

496934.91 5419545.5 264.849

496934.94 5419546.5 265.11099

496934.84 5419544.5 264.78101

Note that the values are either rounded off or the digits after decimal point are altered in the output '.pcd' file. What could be the reason for this?

Sjs
  • 213
  • 1
  • 3
  • 16
  • 2
    As a matter of fact, `boost::loxical_cast` is not at cause here: http://coliru.stacked-crooked.com/a/e47d7cf3fa270efb – YSC Jun 25 '18 at 11:58
  • Worth mentioning is that a `std::setprecision` does **not** in any way enhance / modify the precision of your `double` value. It's a _paint job_ for the standard output strean. The value remains unchanged. – Ron Jun 25 '18 at 12:03
  • How are you determining the value stored in the variable? Your snippet prints with the default precision, which is six significant digits. (Note that the nearest IEEE 754 double is 496934.079000000027008354663849, so that's the value you should get.) – molbdnilo Jun 25 '18 at 12:32
  • @molbdnilo I am developing a program which parses values from a text file line-by-line and stores them as XYZ coordinate values (in float/double format) corresponding to a 3D point with respect to origin. When I verify the coordinates of the points created, I find the digits after decimal point are missing from their XYZ values. – Sjs Jun 25 '18 at 16:38
  • @Ron yes I guessed that. Even with stod() I am getting the same results. I could not figure a way to store the value as it is in the string str. Is it possible? – Sjs Jun 25 '18 at 16:42
  • @molbdnilo If default precision is 6, Is there a way I can adjust the precision of the stored value to something else? Please note that printing the value using 'cout' is not the problem. It is the value which is stored in the 'pVar' variable. – Sjs Jun 25 '18 at 16:53
  • @Sjs The interesting factor is *how* you're verifying the values, not what they're for. How *are* you verifying the values? – molbdnilo Jun 25 '18 at 16:56
  • @molbdnilo I am verifying the values that are written in the in PCD file (which is the coordinate location info of the 3D points). I will give you an example. For the values "496934.079 5419551.839 263.061" in the text file, I found the corresponding values in the PCD file as "496934.09 5419552 263.061". Note that the digits in the first two values are altered. – Sjs Jun 25 '18 at 17:03

1 Answers1

6

boost::lexical_cast<double>(str) already returns the full value 496934.079 as a double. This full value is stored in pVar, and can be used for further processing.

string str = "496934.079";
double pVar = boost::lexical_cast<double>(str); // pVar now contains 496934.079

std::setprecision does not impact the stored value - it merely sets the number of digits (before and after the decimal point) that are displayed. The default display precision is 6, so :

std::cout << pVar << std::endl; // this prints "496934" (6 digits)

Displaying the stored value with a higher precision (eg. 10) gives :

#include <iomanip>

std::cout << std::setprecision(10) << pVar << std::endl; // this prints "496934.079"

But to re-iterate : none of this impacts the stored value. pVar still contains 496934.079. For example :

std::cout << (int) (pVar * 1000) << std::endl; // this displays 496934079

EDIT

The updated code in the question shows that actually, a float is used to store the value, not a double (ref. pcl::PointXYZ).

A float doesn't have enough precision to store the full value 496934.079 - instead it will store the best approximation (496934.09375) it can represent (ref. eg. What is the difference between float and double?).

If you want to ensure you can retain the full value (unmodified), make sure to stick to double.

Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40
  • 2
    This answer does not match the question. It seems that the usage of `cout` was only for exposition; the OP is using `boost::lexical_cast` and specifically asked about that. You will have to show alternatives (e.g. `stringstream` and `.str()`). – Lightness Races in Orbit Jun 25 '18 at 12:06
  • 1
    @LightnessRacesinOrbit : I read the question differently. It's clear to me that the OP is confusing what's being displayed (`496934`) with what's stored in `dbl` by `lexical_cast`. My answer shows that the `lexical_cast` did indeed store the full value (`496934.079`). Furthermore, the OP misunderstands the meaning of precision (shown by his use of `3` to attempt to get the 3 digits after the decimal point). My answer attempts to remove that misunderstanding. – Sander De Dycker Jun 25 '18 at 13:59
  • @SanderDeDycker thanks for the reply. As Lightness Races in Orbit mentioned, printing the value with appropriate precision is not the problem here. I have edited the question. I find the values stored are not the ones I am passing in the string. The number of digits after the decimal point are missing entirely in the stored value. – Sjs Jun 25 '18 at 17:10
  • @Sjs : I've edited my answer to include my comments, and hopefully clarify things – Sander De Dycker Jun 26 '18 at 08:08
  • @SanderDeDycker I am actually developing a program which parses values from a text file line-by-line and stores them as XYZ coordinate values (in float/double format) corresponding to a 3D point with respect to origin. These XYZ coordinate values are saved in a file with extension '.pcd'. When I open it and check the stored values, the digits after the decimal points are varying from its original value (in text file). In some cases, the values are rounded off and in some cases the values after decimal point are altered. I could not figure where this conversion from string to double going wrong – Sjs Jun 26 '18 at 11:32
  • @SanderDeDycker I am editing the question to add entire code that parses value from the txt file and converts it into double. I am also adding the result of some of the converted values that are stored in '.pcd' file. Please have a look. I am using MS Visual studio 2010 compiler. – Sjs Jun 26 '18 at 11:36
  • 2
    @Sjs : your updated code uses `float`, not `double` (ref. [`pcl::PointXYZ`](http://docs.pointclouds.org/trunk/structpcl_1_1_point_x_y_z.html)). A `float` does not have the precision to store the full values that you want to store in them. Ref. eg. https://stackoverflow.com/questions/5098558/float-vs-double-precision – Sander De Dycker Jun 26 '18 at 12:17
  • @Sjs : edited my answer again based on the new information you provided – Sander De Dycker Jun 26 '18 at 12:24
  • @SanderDeDycker thank you so much for the clarification! Thus because pcl::PointXYZ uses float to store the values, I cannot get the exact value of the string values I am passing ? (correct me If I am wrong). Also please clarify if there is any other possible way to store the exact values in 'point.x, point.y and point.z' variables? – Sjs Jun 26 '18 at 14:38
  • 1
    @Sjs : I don't know what the point cloud library offers in that respect. It also depends on what precision you're looking for. A `float` gets you 7-8 digits, a `double` 15-16. Beyond that, there exist libraries that offer arbitrary precision numeric types, or you can opt for a fixed point data type. But first, make sure you actually need the additional precision. – Sander De Dycker Jun 27 '18 at 06:39
  • @SanderDeDycker Thank you san.. I 'll look into it. – Sjs Jun 27 '18 at 06:59