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.
Related
I checked the difference between abs and fabs on python here
As I understand there are some difference regarding the speed and the passed types, but my question related to native c++ on V.S.
Regarding the V.S.
I tried the following on Visual Studio 2013 (v120):
float f1= abs(-9.2); // f = 9.2
float f2= fabs(-9); // Compile error [*]
So fabs(-9) it will give me a compiler error, but when I tried to do the following:
double i = -9;
float f2= fabs(i); // This will work fine
What I understand from the first code that it will not compile because fabs(-9) need a double, and the compiler could not convert -9 to -9.0, but in the second code the compiler will convert i=-9 to i=-9.0 at compile time so fabs(i) will work fine.
Any better explanation?
Another thing, why the compiler can't accept fabs(-9) and convert the int value to double automatically like what we have in c#?
[*]:
Error: more than one instance of overloaded function "fabs" matches the argument list:
function "fabs(double _X)"
function "fabs(float _X)"
function "fabs(long double _X)"
argument types are: (int)
In C++, std::abs is overloaded for both signed integer and floating point types. std::fabs only deals with floating point types (pre C++11). Note that the std:: is important; the C function ::abs that is commonly available for legacy reasons will only handle int!
The problem with
float f2= fabs(-9);
is not that there is no conversion from int (the type of -9) to double, but that the compiler does not know which conversion to pick (int -> float, double, long double) since there is a std::fabs for each of those three. Your workaround explicitly tells the compiler to use the int -> double conversion, so the ambiguity goes away.
C++11 solves this by adding double fabs( Integral arg ); which will return the abs of any integer type converted to double. Apparently, this overload is also available in C++98 mode with libstdc++ and libc++.
In general, just use std::abs, it will do the right thing. (Interesting pitfall pointed out by #Shafik Yaghmour. Unsigned integer types do funny things in C++.)
With C++ 11, using abs() alone is very dangerous:
#include <iostream>
#include <cmath>
int main() {
std::cout << abs(-2.5) << std::endl;
return 0;
}
This program outputs 2 as a result. (See it live)
Always use std::abs():
#include <iostream>
#include <cmath>
int main() {
std::cout << std::abs(-2.5) << std::endl;
return 0;
}
This program outputs 2.5.
You can avoid the unexpected result with using namespace std; but I would adwise against it, because it is considered bad practice in general, and because you have to search for the using directive to know if abs() means the int overload or the double overload.
My Visual C++ 2008 didn't know which to choice from long double fabs(long double), float fabs(float), or double fabs(double).
In the statement double i = -9;, the compiler will know that -9 should be converted to double because the type of i is double.
abs() is declared in stdlib.h and it will deal with int value.
fabs() is declared in math.h and it will deal with double value.
The Boost Format documentation says:
One of its goal is to provide a replacement for printf, that means
format can parse a format-string designed for printf, apply it to the
given arguments, and produce the same result as printf would have.
When I compare the output of boost:format and printf using the same format string I get different outputs. Online example is here
#include <iostream>
#include <boost/format.hpp>
int main()
{
boost::format f("BoostFormat:%d:%X:%c:%d");
unsigned char cr =65; //'A'
int cr2i = int(cr);
f % cr % cr % cr % cr2i;
std::cout << f << std::endl;
printf("Printf:%d:%X:%c:%d",cr,cr,cr,cr2i);
}
The output is:
BoostFormat: A:A:A:65
printf: 65:41:A:65
The difference is when I want to display a char as integral type.
Why there is a difference? Is this a bug or wanted behavior?
This is expected behaviour.
In the boost manual it is written about the classical type-specification you uses:
But the classical type-specification flag of printf has a weaker
meaning in format. It merely sets the appropriate flags on the
internal stream, and/or formatting parameters, but does not require
the corresponding argument to be of a specific type.
Please note also, that in the stdlib-printf call all char arguments are automatically
converted to int due to the vararg-call. So the generated code is identical to:
printf("Printf:%d:%X:%c:%d",cr2i,cr2i,cr2i,cr2i);
This automatic conversion is not done with the % operator.
Addition to the accepted answer:
This also happens to arguments of type wchar_t as well as unsigned short and other equivalent types, which may be unexpected, for example, when using members of structs in the Windows API (e.g., SYSTEMTIME), which are short integers of type WORD for historical reasons.
If you are using Boost Format as a replacement for printf and "printf-like" functions in legacy code, you may consider creating a wrapper, which overrides the % operator in such a way that it converts
char and short to int
unsigned char and unsigned short to unsigned int
to emulate the behavior of C variable argument lists. It will still not be 100% compatible, but most of the remaining incompatibilities are actually helpful for fixing potentially unsafe code.
Newer code should probably not use Boost Format, but the standard std::format, which is not compatible to printf.
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.
So what would be the datatype I am looking at. I know AS3 Number is 64 bit but it is double precision. I am converting code to C++ and since in AS3 it is valid to do this:
var i:Number = 123;
i >> 3; // Yeah shift right a double precision datatype
So in C++ I need now a datatype that is in the integral range of the Number type in AS3 (which is double precision). Please note I am converting and encode/decode functions that were previously used with the AS3 code so I must have the same result.
Thanks in advance.
The AS3 shift operator converts the expression being shifted and the shift amount to 32-bit integers. In C++, you emulate this behavior by casting a double data type to an int and shifting:
#include <iostream>
int main(int argc, char **argv) {
double i(91.5);
int v(static_cast<int>(i) >> 3);
std::cout << "v = " << v << std::endl; // outputs "v = 11"
return 0;
}
Basically, in AS3 Number is a double precision number, so in C++ it'll be double type. But, bit shifts in AS3 are done via implicit conversion. You should check if the result is actually an int, or a double, and if int, you do
i=floor(i/8.0);
and if double, you drop floor() call.
In short, you have to explicitly rewrite operations that are done on ints instead of doubles. But, you can do like (int)i when an operation requires an int, and i is double.
How to use set up decimal precision for all double type numbers in a large C++ program.
I can use stringstream and setprecision(n) to do it but I have to do it one by one for every double number in the whole program.
How to do it globally once for all so that all double type numbers in the program has fixed decimal digits after decimal point (e.g. 4) ?
I do not want to use function call to cause calling overhead.
thanks
double type is not designed to do what you want: it is a floating decimal type, not a fixed decimal type. What you need is some kind of decimal type, but unfortunately C++ does not yet have such type.
It can be emulated most of the times with an integer type where you assume that it represents the then-thousandths of a unit. You just have to be careful in the multiplications and divisions to fix the scale. Additions and subtractions work automatically.
setprecision does not change the precision of double values, but just the precision used when converted into a string.
And converting doubles into strings is relatively expensive operation, so the overhead of a single extra function call should be negligible. If you use double-string conversion in performance critical code, then you are doing it wrong.
My advice would be to just write a function such as:
std::string FmtDbl(double d)
{
std::ostringstream os;
os << std::setprecision(4) << d;
return os.str();
}
And use that function everywhere you need the conversion.