I am facing a conversion issue for which I'd like your help. I'm using gcc4 compiler and I am quite restricted to use gcc4.
I want to convert std::string to double.
std::string aQuantity = aRate.getQuantity();
std::string aAmount = aRate.getAmount();
// aAmount = "22.05"
double dQuantity = boost::lexical_cast<double>(aQuantity);
double dAmount = boost::lexical_cast<double> (aAmount);
// dAmount = 22.050000000000001
By the way, I also tried atof and I still have the same issue. Is there any way to use istringstream with setprecission(2) to get the correct value shown by aAmount?
Due to the nature of floating point values, 22.050000000000001 is the closest value to 22.05 that can be stored. The same would occure if you simply tried to store 22.05 in a double and then print it.
You should set the precision on the output stream if you want to print 22.05. Alternatively you could investigate a rational number library (for example, Boost.Rational). This would be able to store the value 22.05 precisely, unlike a double (or float).
Related
I get an object (msg.data) that is either a number or a string. If it is a string I don't want to use it, if it is a number I want to. I currently solved this problem with an ostringstream, though I think there are way better solutions:
void scan_cb(const sensor_msgs::LaserScan::ConstPtr& scan)
{
float dist = 0.0f;
std::ostringstream s;
s << scan->ranges[0]; // can be string (always "inf") or a float
if(s.str() != "inf"){
dist += scan->ranges[0];
}
...
I care about efficiency, because this is part of a for loop running many times each second.
The basic structure is a ROS message, coming from a certain topic, and can have basically any data type.
In this case I use a LaserScan message, the documentation does not mention that range[x] can return "inf".
According to ROS documentation, scan->ranges is an array of float. That makes sense, because you add it to a float (dist) when the string representation of ranges[0] is not inf.
That means that (as MSalters guessed in its comment), you have a true float value, and you just want to make sure it is a real number and neither an infinite value nor a NaN (Not a Number) value.
So provided you include cmath (or math.h) you can use the C classifications macros to determine whether the number is finite (but subnormal values are allowed) or normal (even subnormal values are rejected):
void scan_cb(const sensor_msgs::LaserScan::ConstPtr& scan)
{
float dist = 0.0f;
if(isfinite(scan->ranges[0])){
dist += scan->ranges[0];
}
...
(more references on IEEE-754 representation of floating point numbers on wikipedia)
I'm parsing a string which may contain either a real or an integral value. I would like to parse that string and get either the integral or the real value in a single parsing.
I could use std::stoi and std::stod, but if i call stoi first and it is a real, then it's going to fail and i will have to call stof, causing a second parsing. And if i call stof first and that the string contains an integral, it's going to consider it as a valid real value, losing the information that it is an integral.
Is there some kind of function that can parse both types in a single pass ? Or do i first have to look for a dot manually and call the right function ?
Thank you. :)
You will not find a standard call to achieve this for the simple reason that a string of digits without a dot is both a valid integer and a valid double.
If your criterion is "double if and only if dot", then look for the dot by hand. Alternatively, read as double and check that the fractional part is null.
Since you said (in the comments above) that simple dot notation is all you want in real numbers, and you want a single-pass (i.e. no back-stepping to already-parsed input), and (again from your comment) are more after the programming experience than efficiency / maintainability / extendability, how about this:
char const * input = /*...*/;
char const * parse_end;
size_t pos;
size_t pos2 = 0;
// parse integer (or pre-digit part of real)
int integer = strtol( input, &parse_end, 10 );
if ( *parse_end == '.' )
{
// you have a real number -- parse the post-digit part
input = parse_end;
double real = strtod( input, &parse_end );
// real + integer is your result
}
else
{
// integer is your result
}
// in either case, parse_end is your position
Why did I use C functions... stoi returns an index, but stod expects a string. So I'd have to do a substr() or similar, while the C functions work with pointers, making things easier.
What I said in my comment holds true: As a brain experiment this holds some value, but any real parsing work should make use of existing solutions like Boost.Spirit. Getting familiar with such building blocks is, IMHO, more valuable than learning how to roll your own.
You should parse it by yourself, using std::string::substr, std::string::find_first_of, std::string::find_first_not_of, etc.
As you know, each of std::stoi and std::stof interprets the first longest substring matching a right representation pattern of required type. You might think the integral-parsed result is always different real-parsed result if both possible, but it isn't.
Example 1: think about "123.". std::stoi will parse the substring "123" and std::stof will parse the whole "123.". "123." is a valid floating-point literal, but it represents an exact integer.
Example 2: think about "123.0". This is a trivial real value representation. std::stoi will parse the substring "123" and std::stof will parse the whole "123.0". Two results evaluate arithmetically same.
This is where you should decide what to parse and what not to. Please see cppreference.com article integer literal and floating-point literal for possible patterns.
With this difficulties, many lexers just tokenize the input (separating it by spaces) and check if the full token matches any of valid representation. I think, If you don't know whether the input is integral or approx real, just parse it by std::stof.
In addition, some solutions casting float to int would cause an erroneous behavior. A float typed variable having integral value is not guaranteed to be evaluated equal to an int typed variable with the same integral value. It's because float, commonly compiled to use float32_t(IEEE 754-1985 single / IEEE 754-2008 binary32) has 24 bits width of significand. So a valid string representation of integer which fits in 32-bit signed, may not fit in float. You lose the precision. double, commonly IEEE 754-2008 binary64, will not lose significand width compared with int32_t, but same problem with int64_t and so on.
Apparently std::stoi does not accept strings representing integers in exponential notation, like "1e3" (= 1000). Is there an easy way to parse such a string into an integer? One would think that since this notation works in C++ source code, the standard library has a way to parse this.
You can use stod (see docs) to do this, by parsing it as a double first. Be wary of precision issues when casting back though...
#include <iostream> // std::cout
#include <string> // std::string, std::stod
int main () {
std::string text ("1e3");
std::string::size_type sz; // alias of size_t
double result = std::stod(text,&sz);
std::cout << "The result is " << (int)result << std::endl; // outputs 1000
return 0;
}
One would think that since this notation works in C++ source code, the standard library has a way to parse this.
The library and the compiler are unrelated. The reason this syntax works in C++ is that the language allows you to assign expressions of type double to integer variables:
int n = 1E3;
assigns a double expression (i.e. a numeric literal of type double) to an integer variable.
Knowing what's going on here you should be able to easily identify the function in the Standard C++ Library that does what you need.
You can read it as a double using standard streams, for example
double d;
std::cin >> d; //will read scientific notation properly
and then cast it to an int, but obviously double can represent far more values than int, so be careful about that.
Emitting exponential notation into std::stoi would overflow too often and integer overflow in C++ is undefined behaviour.
You need to build your own where you can taylor the edge cases to your specific requirements.
I'd be inclined not to go along the std::stod route since a cast from a double to int is undefined behaviour if the integral part of the double cannot be represented by the int.
i'm writing a double value to a file. The numeric value is written with a point as a decimal separator. I would like to use a comma. How i can do that?
The usual way is to use a locale with the decimal separator set to the comma. If your machine is configured for that generally, you can probably just use the nameless locale for it:
std::cout.imbue(std::locale(""));
std::cout << 12345.67;
You can find the answer in an earlier question
This basically changes the locale used by the streams you are using.
I think in the library cmath
there is a function called modf which takes a float or double, and a pointer to an float or double, and returns an integer.
double intPart;
double fractPart;
fractPart = modf(doubleValue, &intPart);
So you pass in the double value, it returns the decimal part as an integer, and the integer value is stored in the pointer you passed in.
You could then write these to file however you want, with a comma in the middle or whatever, just write it as two separate numbers.
float or double
I need to convert decimal number into 64 bit binary float value.
If you know any algorithm or anything about it then please help.
Use boost::lexical_cast.
double num = lexical_cast<double>(decimal);
Assuming you mean a decimal stored inside a string, atof would be a standard solution to convert that to a double value (which is a 64-bit floating point number on the x86 architecture).
std::string s = "0.4";
double convertedValue = atof(s.c_str());
Or similar for C strings:
const char *s = "0.4";
double convertedValue = atof(s);
But if you mean integer number by "decimal number", then just write
int yourNumber = 100;
double convertedValue = yourNumber;
and the value will automatically be converted.
Value casting from a string to double can be implemented by boost::lexical_cast.
Type casting from int to double is a part of C++:
double d = (double)i;
It was already mentioned in the previous replies.
If you are interested to know how this casting is implemented, you may refer the sources of the C standard library your compiler is using given that the sources are provided and no floating point co-processor is used for this purpose. Many embedded target compilers do this work "manually" if no floating point co-processor is available.
For the binary format description, please see Victor's reply
Decimal decimalNumber = 1234;
Float binaryFloatValue = decimalNumber;