PDA

View Full Version : very simple precision question



vonCZ
28th June 2007, 09:30
I've an ofstream, "fout", that I want to set the precision for... but just to the right of the decimal. If the input is 315.12345678 and I set precision like so:


fout << setprecision(5);

I get output like so: 315.12

instead of 315.12346, which is what I want. How can I set precision such that it affects just to the right of the decimal, regardless of what's left of the decimal?

wysota
28th June 2007, 09:35
You are using floats and not doubles. You have to specifically use doubles, otherwise you won't get the precision you require.

vonCZ
28th June 2007, 09:51
could you be more specific? (like how to specify float or double)

The actual input data (loaded into the program using ifstream) might look like this:

3123456
3123456.23
3123456.342356
-- or --
-134
-134.34
-134.3485938485

These are the 2 main types of geographic coordinates I'm working with: UTM (first 3) or Latitue/Longitude. Basically what I want to do--regardless of what the input looks like--is be able to set the output so that there will be 2 values right of the decimal... whether the input is float, double, int, long, etc.

marcel
28th June 2007, 11:00
Like this:
http://www.cplusplus.com/reference/iostream/manipulators/setprecision.html

You have to write doubles in the stream, not floats.

Regards

wysota
28th June 2007, 11:22
The actual input data (loaded into the program using ifstream) might look like this:
If you load it using ifstream then you can load it directly into doubles and you'll be fine.


Basically what I want to do--regardless of what the input looks like--is be able to set the output so that there will be 2 values right of the decimal... whether the input is float, double, int, long, etc.

You'll have to provide some general mechanism for that. The easiest I can think of is to have several implementations of the same base class that do the reading, parsing and whatever else you may need. Something like (that's a major simplification):

struct MyDataStruct {
float long;
float lat;
};

class Base {
virtual ~Base(){}
virtual bool canHandle(const std::string &format) const = 0;
virtual MyDataStruct getData() = 0;
};

class Doubles : public Base {
Doubles(std::ifstream &input) : Base(), str(input){

}
bool canHandle(const std::string &format) const{ return (format=="DOUBLE"); }
MyDataStruct getData(){
MyDataStruct data;
input >> data.long;
input >> data.lat;
return data;
}
private:
std::ifstream &str;
};

class Strings : public Base {
Strings(std::ifstream &input) : Base(), str(input){}
bool canHandle(const std::string &format) const{ return (format=="TEXT"); }
MyDataStruct getData(){
MyDataStruct data;
std::string str;
input >> str;
data.long = atof(str.c_str());
input >> str;
data.lat = atof(str.c_str());
return data;
}
private:
std::ifstream &str;
};
Then you just need to discover what the datatype is (based on some headers or whatever - that's what the "canHandle" method does) and feed the stream into an instance of a proper class.

jacek
28th June 2007, 11:28
Like this:
http://www.cplusplus.com/reference/iostream/manipulators/setprecision.html

You have to write doubles in the stream, not floats.
Actually the link says something different:
On the default floating-point notation, the precision field specifies the maximum number of meaningful digits to display in total counting both those before and those after the decimal point. Notice that it is not a minimum and therefore it does not pad the displayed number with trailing zeros if the number can be displayed with less digits than the precision.
In both the fixed and scientific notations, the precision field specifies exactly how many digits to display after the decimal point, even if this includes trailing decimal zeros. The number of digits before the decimal point does not matter in this case.
So whether the number is a float or a double doesn't have any impact on the stream.

Here's a small example:

#include <iostream>
#include <iomanip>

int main( int argc, char **argv )
{
double d1 = 1.23456789;
double d2 = 12345.6789;
float f1 = 1.23456789;
float f2 = 12345.6789;

std::cout << std::setprecision( 7 );

std::cout << d1 << std::endl;
std::cout << d2 << std::endl;
std::cout << f1 << std::endl;
std::cout << f2 << std::endl;

std::cout << std::fixed;

std::cout << d1 << std::endl;
std::cout << d2 << std::endl;
std::cout << f1 << std::endl;
std::cout << f2 << std::endl;

return 0;
}
And the output:
$ ./a.out
1.234568
12345.68
1.234568
12345.68
1.2345679
12345.6789000
1.2345679
12345.6787109
As you can see, if no notation was set, "precision" means the number of meaningful digits, regardless whether we print a double or a float. After you set notation to fixed, "precision" behaves as one would expect.

vonCZ
28th June 2007, 11:46
yep, that's what I was leaving out: "fixed". Thanks all.