I am trying to place a big number in a C++ variable. The number is 600851475143
I tried unsigned long long int but got an error saying it the constant was too big.
I then tried a bigInt library called BigInt -> http://mattmccutchen.net/bigint/
The problem is I can't compile the code as I get many errors regarding the lib.
undefined reference to `BigInteger::BigInteger(int)' <-- lot's of these.
Here is my code so far:
#include "string"
#include "iostream"
#include "bigint/NumberlikeArray.hh"
#include "bigint/BigUnsigned.hh"
#include "bigint/BigInteger.hh"
#include "bigint/BigIntegerAlgorithms.hh"
#include "bigint/BigUnsignedInABase.hh"
#include "bigint/BigIntegerUtils.hh"
using namespace std;
int main() {
//unsigned long int num = 13195;
//unsigned long long int num = 600851475143;
BigInteger num = 13195;
int divider = 2;
//num = 600851475143;
while (1) {
if ((num % divider) == 0) {
cout << divider << '\n';
num /= divider;
}
else
divider++;
if (num == 1)
break;
}
}
If I put a smaller number and don't use the BigInt lib this program runs fine.
Any help will be appreciated :D
You can specify an integer literal as long by the suffix L.
You can specify an integer literal as long long by the suffix LL.
#include <iostream>
int main()
{
long long num = 600851475143LL;
std::cout << num;
}
The number is 600851475143 isn't too large for a long long int but you need to use the LL suffix when using a long long constants (ULL for unsigned long long int):
unsigned long long int num = 600851475143ULL;
Raison d'etre of a big integer library is to represent integers which your language cannot handle natively. That means, you cannot even write it down as a literal. Probably, that library has a way to parse a string as a big number.
In a more general case when you cannot fit your number in a long long, and can live with the GNU LGPL license (http://www.gnu.org/copyleft/lesser.html), I would suggest trying the GNU Multiprecision Library (http://gmplib.org/).
It is extremely fast, written in C and comes with a very cool C++-wrapper-library.
Is there a bigint lib to link in or a bigint.cpp to compile?
If you are getting undefined reference errors for the bignum library, you probably didn't link it. On Unix, you will have to pass an option like -lbigint. If you are using an IDE, you will have to find the linker settings and add the library.
As for the numbers, as has already been said, a natural constant defaults to int type. You must use LL/ll to get a long long.
The first thing to do in this case is to figure out what is the largest number that you can fit into an unsigned long long. Since it is 64 bit, the largest number would be 2^64-1 = 18446744073709551615, which is larger than your number. Then you know that you are doing something wrong, and you look at the answer by Martin York to see how to fix it.
Try this one.
Basically you can have your own custom class which uses linked list to store the number of infinite size. ( RAM is the restriction )
Try this one
https://mattmccutchen.net/bigint/
For anyone else having problems with this library five years after this question was asked, this is the answer for you.
You cannot just compile your program, it will fail to link with an ugly impenetrable error!
This library is a collection of c++ files which you are supposed to compile to .o files and link against. If you look at the output of the make file provided with the sample program you will see this:
g++ -c -O2 -Wall -Wextra -pedantic BigUnsigned.cc
g++ -c -O2 -Wall -Wextra -pedantic BigInteger.cc
g++ -c -O2 -Wall -Wextra -pedantic BigIntegerAlgorithms.cc
g++ -c -O2 -Wall -Wextra -pedantic BigUnsignedInABase.cc
g++ -c -O2 -Wall -Wextra -pedantic BigIntegerUtils.cc
g++ -c -O2 -Wall -Wextra -pedantic sample.cc
g++ sample.o BigUnsigned.o BigInteger.o BigIntegerAlgorithms.o BigUnsignedInABase.o BigIntegerUtils.o -o sample
Replace sample with the name of your program, paste these lines in a makefile or script, and away you go.
Related
So, i was writing down this code
void shortened(string s){
int cnt=0;
for(int i=0;i<s.size()-1;++i){
cnt++;
}
//some extra code
}
this for loop showed me a warning and i.e. of comparison of integer expressions of different signedness int and string::size_type. But as soon as I changed int i = 0 to unsigned int i=0 there was no warning. I know that the length of the string can never be zero and that's why the warning was shown because int i can hold negative numbers as well. But why the warning was being shown in the first place?
i-0;i<s.size()-1
in itself was very complete. I need to clear my doubt.
Assume you are using g++ as compiler. (gcc is the same while clang is unfamiliar to me)
This warning comes from the compilation option -Wall which asks the compiler to give you detailed warning for everything( Wall = Warning All). (For more information, you can visit https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options)
So g++ -o tmp tmp.cpp won't show such warning but g++ -o tmp -Wall tmp.cpp will.
Come back to the main topic: such a wired warning is shown due to the return type for string.size() is size_t and size_t is one of the unsigned types.
On my machine, I find size_t is defined in stddef.h as followed:
#define __SIZE_TYPE__ long unsigned int
typedef __SIZE_TYPE__ size_t;
You compare between an int and an unsigned int in for statement and this why here is such a warning.
I run an up to date debian testing (with kernel 4.19).
Helpers are not found on my system (but they exist in the header, Qt jumps to them)
#include "bpf/bpf.h"
int main (){
int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
return 0;
}
Compilation results in
undefined reference to `bpf_create_map(bpf_map_type, int, int, int, unsigned int)'
compiled with
g++ -c -pipe -g -std=gnu++1z -Wall -W -fPIC -DQT_QML_DEBUG -I. -I../../Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
g++ -lbpf -o server main.o
Same result with
g++ main.cpp -lbpf -o out
I have the libbpf-dev installed as well and i have the associated libraries (a and so).
What is wrong?
Update
even the following code won't work
#include <linux/bpf.h>
int main (){
//int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
bpf_attr attr = {};
attr.map_type = BPF_MAP_TYPE_ARRAY;
attr.key_size = 1;
attr.value_size = 1;
attr.max_entries = 1;
bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return 0;
}
results in
error: 'bpf' was not declared in this scope
Update2:
BTW, key size is mandated to be 4 and not 1; but it is a point aside, that was unrelated to my problem here.
Namespace issue due to compiling in C++, you probably want:
extern "C" {
#include "bpf/bpf.h"
}
int main()...
Regarding your second error (error: 'bpf' was not declared in this scope), this is not directly related to libbpf, this is because there is no function simply called bpf() to actually perform the syscall. Instead you have to use the syscall number. For example, libbpf defines the following:
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}
... and uses sys_bpf() after that, the same way you try to call bpf() in your sample.
For the record, “BPF helpers” often designates BPF functions that you call from within a BPF program, which is not the case here. Hence some confusion in the comments, I believe.
See that example:
//test.cpp
#include <iostream>
void test(unsigned int i, int j) {
std::cout << i << " " << j << std::endl;
}
int main() {
test(-1, -1);
int x = -1;
test(x,x);
return 0;
}
with:
$ g++ -Wall -Wextra -Wpedantic test.cpp:
4294967295 -1
4294967295 -1
Why does gcc let that slip? And is there an option to detect such an implicit conversion?
Cheers
This has been answered before. One of the reasons is because C allowed it, and c++ was meant to be backwards compatible. Some compilers will warn, though I tested on gcc 5.2 and it does not have an option to turn that warning on.
See: Why does C++ allows implicit conversion from int to unsigned int?
#
Just found from one of the other answers that you need to add the -Wsign-conversion flag. Seems -Wall should do that but doesn't.
Yup, I found it. Misassumed that (-Wall -Wextra -W -Wpedantic -Wconversion) would cover it all. But in
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
the missing flag is: -Wsign-conversion
I have written a small test where I'm trying to compare the run speed of resizing a container and then subsequently using std::generate_n to fill it up. I'm comparing std::string and std::vector<char>. Here is the program:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>
int main()
{
std::random_device rd;
std::default_random_engine rde(rd());
std::uniform_int_distribution<int> uid(0, 25);
#define N 100000
#ifdef STRING
std::cout << "String.\n";
std::string s;
s.resize(N);
std::generate_n(s.begin(), N,
[&]() { return (char)(uid(rde) + 65); });
#endif
#ifdef VECTOR
std::cout << "Vector.\n";
std::vector<char> v;
v.resize(N);
std::generate_n(v.begin(), N,
[&]() { return (char)(uid(rde) + 65); });
#endif
return 0;
}
And my Makefile:
test_string:
g++ -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test test.cpp -DSTRING
valgrind --tool=callgrind --log-file="test_output" ./test
cat test_output | grep "refs"
test_vector:
g++ -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test test.cpp -DVECTOR
valgrind --tool=callgrind --log-file="test_output" ./test
cat test_output | grep "refs"
And the comparisons for certain values of N:
N=10000
String: 1,865,367
Vector: 1,860,906
N=100000
String: 5,295,213
Vector: 5,290,757
N=1000000
String: 39,593,564
Vector: 39,589,108
std::vector<char> comes out ahead everytime. Since it seems to be more performant, what is even the point of using std::string?
I used #define N 100000000. Tested 3 times for each scenario and in all scenarios string is faster. Not using Valgrind, it does not make sense.
OS: Ubuntu 14.04. Arch:x86_64 CPU: Intel(R) Core(TM) i5-4670 CPU # 3.40GHz.
$COMPILER -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test x.cc -DVECTOR
$COMPILER -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test x.cc -DSTRING
Times:
compiler/variant | time(1) | time(2) | time(3)
---------------------------+---------+---------+--------
g++ 4.8.2/vector Times: | 1.724s | 1.704s | 1.669s
g++ 4.8.2/string Times: | 1.675s | 1.678s | 1.674s
clang++ 3.5/vector Times: | 1.929s | 1.934s | 1.905s
clang++ 3.5/string Times: | 1.616s | 1.612s | 1.619s
std::vector comes out ahead everytime. Since it seems to be more
performant, what is even the point of using std::string?
Even if we suppose that your observation holds true for a wide range of different systems and different application contexts, it would still make sense to use std::string for various reasons, which are all rooted in the fact that a string has different semantics than a vector. A string is a piece of text (at least simple, non-internationalised English text), a vector is a collection of characters.
Two things come to mind:
Ease of use. std::string can be constructed from string literals, has a lot of convenient operators and can be subject to string-specific algorithms. Try std::string x = "foo" + ("bar" + boost::algorithm::replace_all_copy(f(), "abc", "ABC").substr(0, 10) with a std::vector<char>...
std::string is implemented with Small-String Optimization (SSO) in MSVC, eliminating heap allocation entirely in many cases. SSO is based on the observation that strings are often very short, which certainly cannot be said about vectors.
Try the following:
#include <iostream>
#include <vector>
#include <string>
int main()
{
char const array[] = "short string";
#ifdef STRING
std::cout << "String.\n";
for (int i = 0; i < 10000000; ++i) {
std::string s = array;
}
#endif
#ifdef VECTOR
std::cout << "Vector.\n";
for (int i = 0; i < 10000000; ++i) {
std::vector<char> v(std::begin(array), std::end(array));
}
#endif
}
The std::string version should outperform the std::vector version, at least with MSVC. The difference is about 2-3 seconds on my machine. For longer strings, the results should be different.
Of course, this does not really prove anything either, except two things:
Performance tests depend a lot on the environment.
Performance tests should test what will realistically be done in a real program. In the case of strings, your program may deal with many small strings rather than a single huge one, so test small strings.
I was writing some templated code to benchmark a numeric algorithm using both floats and doubles, in order to compare against a GPU implementation.
I discovered that my floating point code was slower and after investigating using Vtune Amplifier from Intel I discovered that g++ was generating extra x86 instructions (cvtps2pd/cvtpd2ps and unpcklps/unpcklpd) to convert some intermediate results from float to double and then back again. The performance degradation is almost 10% for this application.
After compiling with the flag -Wdouble-promotion (which BTW is not included with -Wall or -Wextra), sure enough g++ warned me that the results were being promoted.
I reduced this to a simple test case shown below. Note that the ordering of the c++ code affects the generated code. The compound statement (T d1 = log(r)/r;) produces a warning, whilst the separated version does not (T d = log(r); d/=r;).
The following was compiled with both g++-4.6.3-1ubuntu5 and g++-4.7.3-2ubuntu1~12.04 with the same results.
Compile flags are:
g++-4.7 -O2 -Wdouble-promotion -Wextra -Wall -pedantic -Werror -std=c++0x test.cpp -o test
#include <cstdlib>
#include <iostream>
#include <cmath>
template <typename T>
T f()
{
T r = static_cast<T>(0.001);
// Gives no double promotion warning
T d = log(r);
d/=r;
// Promotes to double
T d1 = log(r)/r;
return d+d1;
}
int main()
{
float f1 = f<float>();
std::cout << f1 << std::endl;
}
I realise that the c++11 standard allows the compiler discretion here. But why does the order matter?
Can I explicitly instruct g++ to use floats only for this calculation?
EDIT: SOLVED by Mike Seymour. Needed to use std::log to ensure picking up the overloaded version of log instead of calling the C double log(double). The warning was not generated for the separated statement because this is a conversion and not a promotion.
The problem is
log(r)
In this implementation, it seems that the only log in the global namespace is the C library function, double log(double). Remember that it's not specified whether or not the C-library headers in the C++ library dump their definitions into the global namespace as well as namespace std.
You want
std::log(r)
to ensure that the extra overloads defined by the C++ library are available.