I need to handle sub-metre coordinates in C++ which have large integer parts (e.g. 515876.12 // 5117789.22), but I'm having issues with rounding:
double inUTMX = 560351.12 is displayed as 560351
double inUTMY = 5113570.22 is displayed as 5.11357e+06
I can normalise the coordinates for processing if necessary (e.g. /1e5), but I need to read-in the sub-metre coordinates via command line in the first place. Trouble is they always get rounded.
Is there a neat way to deal with doubles that have large integer values in C++?
(Tried it in Python it stores the entire precision fine as a float, just wondering where I'm going wrong.)
Any ideas / pointers much appreciated.
You can modify how doubles are streamed by using std::setprecision.
Example:
#include <iostream>
#include <iomanip>
int main () {
double inUTMX = 560351.12;
double inUTMY = 5113570.22;
std::cout << std::setprecision(20) << inUTMX << std::endl;
std::cout << std::setprecision(20) << inUTMY << std::endl;
return 0;
}
Output:
560351.11999999999534
5113570.2199999997392
Related
I'm trying to format a duration with fmt's chrono impl and specify the precision for the seconds part.
I'm reading the documentation but think i don't understand how to do it; whatever i try, it either doesn't format as expected or the compiler reports an error.
Here's what i tried so far:
#include <chrono>
#include <ratio>
#define FMT_HEADER_ONLY
#include <fmt/chrono.h>
#include <iostream>
int main() {
std::chrono::duration<std::int64_t, std::nano> const d{3601123456789};
std::cout << fmt::format("1a {:%H:%M:%S}\n", d);
std::cout << fmt::format("1_ {: >15%S} <-- width works; precision won't compile\n", d);
// The fmt docs say that "Precision is valid only for std::chrono::duration types with a floating-point representation type."
// The following format doesn't compile with "d" whose ticks are represented as integer.
// It does with "dd" whose ticks are represented as double, but the result is still not as expected.
std::cout << fmt::format("2_ {:.2%S} <-- this is confusing; precision doesn't work\n", dd);
std::cout << fmt::format("2_ {: >15.2%S} <-- width works; precision doesn't\n", dd);
}
(godbolt link)
Edit:
Just checked with std::format on msvc; the results are the same.
To control the width, include an alignment and width specification as the first thing after the ':'. For example "{:>20..." to say align right with width 20.
To control the precision, alter the units of the input duration. For example to have 3 decimal digits, floor<milliseconds>(d):
std::cout << fmt::format("d: {:>20%H:%M:%S}\n", std::chrono::floor<std::chrono::milliseconds>(d));
Output:
d: 00:02:03.456
If you prefer, you can use {:>20%T} in place of {:>20%H:%M:%S}.
For two fractional digits it would be convenient to create a centiseconds duration:
using centiseconds = std::chrono::duration<std::int64_t, std::centi>;
std::cout << fmt::format("d: {:>20%T}\n", std::chrono::floor<centiseconds>(d));
Getting a little winded from chasing the goalposts here ... ;-)
using centiseconds = chrono::duration<int64_t, centi>;
auto d = 3601123456us;
auto m = floor<minutes>(d);
d -= m;
cout << fmt::format("{}:{:%S}", m/1min, floor<centiseconds>(d)) << '\n';
Output:
60:01.12
I got this working for specifying the precision in the format string, but this exits the chrono-type system completely prior to formatting:
auto d = 3601123456.us;
auto m = floor<minutes>(d);
d -= m;
cout << fmt::format("{}:{:0>5.2f}", m/1min, d/1s) << '\n';
Output:
60:01.12
I am still quite new in the C++ business.
I want to output a float number with only one decimal number.
At first I thought it would work with Modulo (%), but I quickly discarded this. Then I wanted to solve it calculated, but I couldn't solve this.
There is also a clue. I can only use <iostream> and <fstream>.
But now I came across the function setprecision().
My output code is.
cout<<fixed<<setprecision(2)<<variable<<endl;
However, it outputs e.g. 2.99. I need 2.9 though.
cout<<fixed<<setprecision(1)<<variable<<endl;
Outputs 3.0, though.
Please help me, I will be infinitely grateful. :)
Illustrating the floating-point environment solution from Sebastian in the comments
#include <fenv.h>
#include <iostream>
#include <iomanip>
int main() {
if (fesetround(FE_TOWARDZERO)) {
// need to check for non-zero error condition
std::cerr << "Unable to set correct rounding direction" << std::endl;
return 1;
}
float value = 2.99f;
std::cout << std::setprecision(2) << value << std::endl;
}
This prints
2.9
Note that this will also affect other floating point calculations, which may cause unexpected results.
I don't know how widespread support is for these different rounding directions on different target architectures, so if you want extreme portability you'll need to provide a back up solution if fesetround returns a non-zero value.
godbolt
Here's one way:
#include <math.h>
#include <iostream>
int main() {
auto f = 2.9999;
std::cout << trunc(f * 10) / 10 << '\n';
}
Sebastian solved it in the comments.
cout<< fixed<<setprecision(1)<<variable-.05<<endl;
Thank you all for contributing.
I'll try to improve my
Using the GSL (GNU Scientific Library), I'm trying to understand why gsl_vector_view_array() returns a slighly modified value after assignment.
In the code below, I declare a vector_view 'qview_test' which is linked to table q_test[0]=0.0 and display its value which is 0.0. Then, I change the value of q_test[0]=1.12348 and expecting the same value for qview_test, but it gets alterated to qview_test=1.1234800000000000341771055900608189.
How do you explain such a result ? How to replicate the result without GSL ?
#include <iostream>
#include <gsl/gsl_blas.h>
using namespace std;
double q_test[1]={0.0};
gsl_vector_view qview_test;
int nb_variable = 1;
int main()
{
qview_test=gsl_vector_view_array(q_test,nb_variable);
cout.precision(35);
cout << "qview before: " << gsl_vector_get(&qview_test.vector,0)<< endl;
// Assign value
q_test[0]=1.12348;
cout << "qview after: " << gsl_vector_get(&qview_test.vector,0) << endl;
return 0;
}
Thanks for any help,
H.Nam
This looks like floating point rounding to me.
Basically any decimal number can only have a finite precision and all numbers in between get rounded to the nearest float.
I am not familiar with gsl so I don't know why it's displaying so many digits.
In other words, to get more precise give your number more bits (128 bit float or something like that) to be represented. This will give you more precision, however you most likely won't need it.
#include <iostream>
using namespace std;
int main()
{
cout.precision(32);
float val = 268433072;
float add = 13.5;
cout << "result =" << (val + add) << endl;
}
I'm compiling the above program with standard g++ main.cc
and running it with ./a.out
The ouput I receive however, is,
result =268433088
Clearly, this is not the correct answer..Why is this happening?
EDIT: This does not occur when using double in place of float
You can reproduce your "float bug" with an even simpler piece of code
#include <iostream>
using namespace std;
int main()
{
cout.precision(32);
float val = 2684330722;
cout << "result =" << val << endl;
}
The output
result =2684330752
As you can see the output does not match the value val was initialized with.
As it has been stated many times, floating-point types have limited precision. Your code sample simply exceeded that precision, so the result got rounded. There's no "bug" here.
Aside from the reference to (1991, PDF) What Every Computer Scientist Should Know About Floating-Point Arithmetic
The short answer is, that because float has limited storage (like the other primitives too) the engineers had to make a choice: which numbers to store with which precision. For the floating point formats they decided to store numbers of small magnitude precisely (some decimal digits), but numbers of large magnitude very imprecisely, in fact starting with +-16,777,217 the representable numbers are becoming so thin that not even all integers are represented which is the thing you noticed.
Actually I am working on range expression in c++. So what I want is if I have any expression like
x<1
Then my
double getMax(...);
should return a double value that is just before 1.000 (double precision) on a number line.
I tried doing this
double getMax(double& a)
{
return (a-numeric_limits<double>::min());
}
But I am still getting same value as a in return statement.
I think C++ is converting it to nearest double in cout statement.
int main()
{
double a = 32;
cout<<scientific<<getMax(a)<<endl;
return 0;
}
output:
3.200000e+001
First of all, you need to ensure that you actually print sufficiently many digits to ensure all representable values of double are displayed. You can do this as follows (make sure you #include <iomanip> for this):
std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << getMax(a) << std::endl;
Secondly, numeric_limits<>::min is not appropriate for this. If your starting value is 1.0, you can use numeric_limits<double>::epsilon, which is the smallest difference from 1.0 that is representable.
However, in your code example, the starting value is 32. Epsilon does not necessarily work for that. Calculating the right epsilon in this case is difficult.
However, if you can use C++11(*), there is a function in the cmath header that does what you need std::nextafter:
#include <iostream>
#include <limits>
#include <iomanip>
#include <cmath>
double getMax(double a)
{
return std::nextafter(a,std::numeric_limits<double>::lowest());
}
int main()
{
double a = 32;
std::cout << std::scientific
<< std::setprecision(std::numeric_limits<double>::max_digits10)
<< getMax(a)
<< std::endl;
return 0;
}
I've also put it on liveworkspace.
To explain:
double nextafter(double from, double to);
returns the next representable value of from in the direction of to. So I specified std::numeric_limits<double>::lowest() in my call to ensure you get the next representable value less than the argument.
(*)See Tony D's comment below. You may have access to nextafter() without C++11.
I think you've got the right idea.
Check out Setting the precision of a double without using stream (ios_base::precision) not so much for the question, but for the examples they give of using precision. You might want to try something like printing with a precision of 53.
The way I usually see "close to but not quite" involves setting a difference threshold (typically called epsilon). In that case, you wouldn't use a getMax function, but have an epsilon used in your usage of less than. (You could do a class with the epsilon value and operator overloading. I tend to avoid operator overloading like a plague.)
Basically, you'd need:
bool lessThanEpsilon(double number, double lessThan, double epsilon)
{
return (lessThan - number >= epsilon);
}
There are other varieties, of course. Equals would check if Math.abs(number - equals) < epsilon