How to use the C++ max function with boost 128 bit integer - c++

If I have the following code:
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision
int main()
{
int128_t a = Func_a()
int128_t b = Func_b()
std::cout << std::max(a, b) << std::endl;
return 0;
}
And if I compile using g++ on Ubuntu, I get the following error:
error: cannot convert ‘const boost::multiprecision::number >’ to ‘int64 {aka long long int}’ in assignment
What is the proper way to compare two int128_t numbers to see which one is greater?
EDIT: I am using std::max.

Your code (except for missing semicolons) compiles and runs without error.
However, according to your compiler message, I'm suspecting that in
int128_t a = Func_a(); // are you really sure it is int128_t?
the left-hand side is not a boost::multiprecision::int128_t, since the compiler says it is a int64.

Related

Different results using same function from different libraries

Here is some code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long int a, b;
long long int c;
cin >> a >> b;
c = abs(a) + abs(b);
cout << c;
cout << endl;
}
Which supposed to return 1000000000000000002 when I input 1000000000000000000 and 2.
If I try to do it with cmath it will return 1000000000000000000, but if I use cstdlib it will return 1000000000000000002. Why is that even happening?
Also considering that I'm using cmath, shouldn't it work even more proper?
I'm using Linux Mint 18.2 64bit, Eclipse Platform.
The cmath version is a float one. So when you only have that one, you actually do the computation on floats and convert back into a long long at the end. Float precision not being enough to hold 18 digits, the +2 simply gets lost.
The cstdlib version is a integer one. Which gives the expected result.
As pointed out in the comments, in C++11, cmath also defines a version of abs that takes integers. However, “these overloads effectively cast x to a double before calculations (defined for T being any integral type)”.
I believe your compiler should give you a warning for the conversions if you use -Wall -Wextra or similar flags while only inclulding cmath.
If you are using g++, try to compile both versions with -Wconversion (or -Wfloat-conversion).
Note that the <cmath> version generates a warning:
main.cpp:14:7: warning: conversion to ‘long long int’ from ‘__gnu_cxx::__enable_if::__type {aka double}’ may alter its value [-Wfloat-conversion]
c = abs(a) + abs(b);
While the <cstdlib>version compiles without warnings.
That is because, in <cmath>, abs() is defined as1:
float abs(float);
double abs(double);
long double abs(long double);
While in <cstdlib> it is defined as1:
int abs(int);
long abs(long);
long long abs(long long);
1The integer versions of abs() are defined in <cmath> since C++17.

C++ code fails to compile with error 'long type-name' is invalid

I prefer to avoid using typedef preferring using instead but I have stumbled across the situation where I have to use it since the code outputted by thrift (version 0.9.3) uses a typedef. The smallest instance of the error comes in the following code
#include <iostream>
using namespace std;
typedef int64_t long;
typedef int32_t int;
int main() {
cout << "Hello world " << endl;
return 0;
}
The error I get is
test.cpp:4:17: error: 'long type-name' is invalid
typedef int64_t long;
^
test.cpp:4:1: error: typedef requires a name [-Werror,-Wmissing-declarations]
typedef int64_t long;
^~~~~~~~~~~~~~~~~~~~
test.cpp:5:17: error: cannot combine with previous 'type-name' declaration specifier
typedef int32_t int;
^
test.cpp:5:1: error: typedef requires a name [-Werror,-Wmissing-declarations]
typedef int32_t int;
^~~~~~~~~~~~~~~~~~~
4 errors generated.
The output I get from g++ --version is
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
Could someone help with this error?
long is a keyword in c++, so you cannot create a type with name long. See the list.
But the question is with Thrift generated code. I did some experiments with Thrift, and I can reproduce the problem by adding this line to the official tutorial.thrift file:
typedef i64 long
Apparently Thrift won't check whether this is going to compile or not. So you need to make sure your typedef is ok with all possible languages.
It should be
typedef long int64_t;
typedef int int32_t;
Typedefs work like variable declarations, just with typedef in front.

C++ Type Check in Functions ignored (required double, provided int)

I have the following code
#include <iostream>
using namespace std;
int dmult(int a, int b){
return 2*a*b;
}
int main(void)
{
double a = 3.3;
double b = 2;
int c = dmult(a,b);
cout << c << endl;
return 0;
}
It compiles with MinGW without problems. The result is (as I thought) false. Is it a problem of the compiler that there is no warning, that a function expecting integers, but fed with doubles, can compile without warning even if the input type is wrong? Does it mean that C++ ignores the input type of a function? Shouldn't it realize that the function arguments have the wrong type?
double's are implicitly convertible to ints (and truncated), and the compiler is not forced by the standard to emit a warning (it tries its best to perform the conversion whenever possible). Compile with -Wconversion
g++ -Wconversion program.cpp
and you'll get your warning:
warning: conversion to 'int' from 'double' may alter its value [-Wfloat-conversion]
The typical warning flags -Wall -Wextra don't catch it since many times it is the programmer's intention to truncate double's to int's.
Live example here.
c++ automatically casts floats and doubles to integer literals by truncating them. so 3.3 becomes 3 when you call dmult(3.3,2)

Why does g++ 4.8.1 issue a conversion warning

When I compile the code below with g++ 4.8.1 (64bit) in this way:
$ g++ -Wconversion -o main main.cpp
I get this result:
main.cpp: In function ‘int main()’:
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
int i = sizeof(x)/sizeof(x[0]);
^
My expectation would be that the compiler should be able to evaluate the expression at compile time. If you make a similar program in plain c, gcc works like a charm.
Should this be considered a bug in g++ (e.g. clang++ does not have this problem)?
if you change the problematic line to something like:
char c = 0x10000000/0x1000000;
then the compiler does not complain. This suggest that some constant evaluation is done before warning generation.
main.cpp:
#include <iostream>
struct foo {
int a;
int b;
};
foo x[50];
int main()
{
int i = sizeof(x)/sizeof(x[0]);
std::cout << i << std::endl;
return 0;
}
int i = sizeof(x)/sizeof(x[0]);
//int <-- std::size_t <-- std::size_t / std::size_t
The type of the expression sizeof(x)/sizeof(x[0]) is std::size_t which on your machine is unsigned long int. So conversion from this type to int is data-loss, if the source is bigger in size than the target.
Though, I agree that in your case, there would not be actual data-loss if the compiler actually computes the value, but I guess it applies -Wconversion before the actual computation.
sizeof() returns you std::size_t not int! So cast it or declare i as std::size_t.
std::size_t i = sizeof(x)/sizeof(x[0]);

Compilation error while using to_string in c++ program

To get precision and scale of a number i am using this simple program. But while converting number into string it is giving compilation error.
g++ precision.cpp
precision.cpp: In function ‘int main()’:
precision.cpp:6: error: ‘to_string’ was not declared in this scope
When I compile with the -std=c++0x switch I get
g++ precision.cpp -std=c++0x
precision.cpp: In function ‘int main()’:
precision.cpp:6: error: call of overloaded ‘to_string(int)’ is ambiguous
/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../../include/c++/4.4.4/bits/basic_string.h:2604: note: candidates are: std::string std::to_string(long long int)
/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../../include/c++/4.4.4/bits/basic_string.h:2610: note: std::string std::to_string(long long unsigned int)
/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../../include/c++/4.4.4/bits/basic_string.h:2616: note: std::string std::to_string(long double)
The source code looks like this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string value = to_string(static_cast<int>(1234));
int precision = value.length();
int scale = value.length()-value.find('.')-1;
cout << precision << " " << scale;
return 0;
}
What is causing this error?
The first error is because std::to_string is a C++11 feature, and GCC by default compiles in C++03 mode.
The second error, when you are using the correct flag, is probably because the support for C++11 in GCC 4.4 (which you seem to be using) is quite minimal. As you can see by the error messages, the compiler shows you the alternatives it have.
By the way, you don't need to cast integer literals to int, they are of type int by default. You might want to cast it to long double though, as that's one of the valid overloads and you seems to want to find the decimal point (the code will not work as expected if there is no decimal point in the string, like when converting an integer).
I recommend to use boost::lexical_cast instead.