I'm programming in C++ and I have to store big numbers in one of my exercices.
The biggest number i have to store is : 9 780 321 563 842.
Each time i try to print the number (contained in a variable) it gives me a wrong result (not that number).
A 32bit type isn't enough since 2^32 is a 10 digit number and I have to store a 13 digit number. But with 64 bits you can respresent a number that has 20digits. So I tried using the type "uint64_t" but that didn't work for me and I really don't understand why.
So I searched on the internet to find which type would be sufficient for my variable to fit in. I saw on this forum persons with the same problem but they solved it using long long int or long double as type. But none worked for me (neither did long float).
I really don't know which other type could store that number, as I tried a lot but nothing worked for me.
Thanks for your help! :)
--
EDIT : The code is a bit long and complex and would not matter for the question, so this is actually what I do with the variable containing that number :
string barcode_s = "9780321563842";
uint64_t barcode = atoi(barcode_s.c_str());
cout << "Barcode is : " << barcode << endl;
Off course I don't put that number in a variable (of type string) "barcode_s" to convert it directly to a number, but that's what happen in my program. I read text from an input file and put it in "barcode_s" (the text I read and put in that variable is always a number) and then I convert that string to a number (using atoi).
So i presume the problem comes from the "atoi" function?
Thanks for your help!
The problem is indeed atoi: it returns an int, which is on most platforms a 32-bits integer. Converting to uint64_t from int will not magically restore the information that has been lost.
There are several solutions, though. In C++03, you could use stringstream to handle the conversion:
std::istringstream stream(barcode_s);
unsigned long barcode = 0;
if (not (stream >> barcode)) { std::abort(); }
In C++11, you can simply use stoul or stoull:
unsigned long long const barcode = std::stoull(barcode_s);
Your number 9 780 321 563 842 is hex 8E52897B4C2, which fits into 44 bits (4 bits per hex digit), so any 64 bit integer, no matter if signed or unsigned, will have space to spare. 'uint64_t' will work, and it will even fit into a 'double' with no loss of precision.
It follows that the remaining issue is a mistake in your code, usually that is either an accidental conversion of the 64 bit number to another type somewhere, or you are calling the wrong fouction to print a 64 bit integer.
Edit: just saw your code. 'atoi' returns int. As in 'int32_t'. Converting that to 'unit64_t' will not reconstruct the 64 bit number. Have a look at this: http://msdn.microsoft.com/en-us/library/czcad93k.aspx
The atoll () function converts char* to a long long.
If you don't have the longer function available, write your own in the mean time.
uint64_t result = 0 ;
for (unsigned int ii = 0 ; str.c_str()[ii] != 0 ; ++ ii)
{
result *= 10 ;
result += str.c_str () [ii] - '0' ;
}
Related
This might be a really simple question for some, but I'm new to C++ and hope someone can answer this for me.
I'm using this online C++ compiler. Here's the simple code I'm running in it:
int main()
{
int x = 1- 2;
std::cout << x << std::endl;
return x;
}
The output is:
-1
...Program finished with exit code 255
Press ENTER to exit console.
That really ponders me. Why would the main() function return 255 when the value of x is -1?
Doesn't main() return an int (not an unsigned int), so it should be able to return a negative number, right?
How does -1 get converted to 255? Something to do with an 8-bit variable? But isn't the int type 16-bit?
This is not related to C language really. The operating system, or possibly just the C runtime (the small piece of the code which sets up things for your C program and actually calls your main function) limits exit code of the program to unsigned 8 bit number.
Very nearly all systems today use two's complement representation for negative numbers, and then bit pattern for -1 is having all bits of the number to be 1. Doesn't matter how many bits, they are all set when value is -1.
The simplest way to convert an int to 8 bit number is to just take 8 lowest bits (which are now all 1 as per above), so you end up with binary number:
11111111
If interpreted as unsigned, then in decimal value of this happens to be 255 (as signed 8 bits it is still -1), which you can check with any calculator which supports binary (such as Windows 10 Calculator app when you switch it to Programmer mode).
Looking at this from the opposite direction: When trying to understand funny numbers related to computers or programming, it is often useful to convert them to binary. If you convert 255 to binary, you get 11111111, and then if you know binary numbers, you should realize this is -1 if interpreted as signed 8 bit number.
I've recently needed to convert mnist data-set to images and labels, it is binary and the structure is in the previous link, so i did a little research and as I'm fan of c++ ,I've read the I/O binary in c++,after that I've found this link in stack. That link works well but no code commenting and no explanation of algorithm so I've get confused and that raise some question in my mind which i need a professional c++ programmer to ask.
1-What is the algorithm to convert the data-set in c++ with help of ifstream?
I've realized to read a file as a binary with file.read and move to the next record, but in C , we define a struct and move it inside the file but i can't see any struct in c++ program for example to read this:
[offset] [type] [value] [description]
0000 32 bit integer 0x00000803(2051) magic number
0004 32 bit integer 60000 number of images
0008 32 bit integer 28 number of rows
0012 32 bit integer 28 number of columns
0016 unsigned byte ?? pixel
How can we go to the specific offset for example 0004 and read for example 32 bit integer and put it to an integer variable.
2-What the function reverseInt is doing? (It is not obviously doing simple reversing an integer)
int ReverseInt (int i)
{
unsigned char ch1, ch2, ch3, ch4;
ch1 = i & 255;
ch2 = (i >> 8) & 255;
ch3 = (i >> 16) & 255;
ch4 = (i >> 24) & 255;
return((int) ch1 << 24) + ((int)ch2 << 16) + ((int)ch3 << 8) + ch4;
}
I've did a little debugging with cout and when it revised for example 270991360 it return 10000 , which i cannot find any relation, I understand it AND the number multiples with two with 255 but why?
PS :
1-I already have the MNIST converted images but i want to understand the algorithm.
2-I've already unzip the gz files so the file is pure binary.
1-What is the algorithm to convert the data-set in c++ with help of ifstream?
This function read a file (t10k-images-idx3-ubyte.gz) as follow:
Read a magic number and adjust endianness
Read number of images and adjust endianness
Read number rows and adjust endianness
Read number of columns and adjust endianness
Read all the given images x rows x columns characters (but loose them).
The function use normal int and always switch endianness, that means it target a very specific architecture and is not portable.
How can we go to the specific offset for example 0004 and read for example 32 bit integer and put it to an integer variable.
ifstream provides a function to seek to a given position:
file.seekg( posInBytes, std::ios_base::beg);
At the given position, you could read the 32-bit integer:
int32_t val;
file.read ((char*)&val,sizeof(int32_t));
2- What the function reverseInt is doing?
This function reverse order of the bytes of an int value:
Considering an integer of 32bit like aaaaaaaabbbbbbbbccccccccdddddddd, it return the integer ddddddddccccccccbbbbbbbbaaaaaaaa.
This is useful for normalizing endianness, however, it is probably not very portable, as int might not be 32bit (but e.g. 16bit or 64bit)
I hope this finds you well.
I am trying to convert an index (number) for a word, using the ASCII code for that.
for ex:
index 0 -> " "
index 94 -> "~"
index 625798 -> "e#A"
index 899380 -> "!$^."
...
As we all can see, the 4th index correspond to a 4 char string. Unfortunately, at some point, these combinations get really big (i.e., for a word of 8 chars, i need to perform operations with 16 digit numbers (ex: 6634204312890625), and it gets really worse if I raise the number of chars of the word).
To support such big numbers, I had to upgrade some variables of my program from unsigned int to unsigned long long, but then I realized that modf() from C++ uses doubles and uint32_t (http://www.raspberryginger.com/jbailey/minix/html/modf_8c-source.html).
The question is: is this possible to adapt modf() to use 64 bit numbers like unsigned long long? I'm afraid that in case this is not possible, i'll be limited to digits of double length.
Can anyone enlight me please? =)
16-digit numbers fit within the range of a 64-bit number, so you should use uint64_t (from <stdint.h>). The % operator should then do what you need.
If you need bigger numbers, then you'll need to use a big-integer library. However, if all you're interested in is modulus, then there's a trick you can pull, based on the following properties of modulus:
mod(a * b) == mod(mod(a) * mod(b))
mod(a + b) == mod(mod(a) + mod(b))
As an example, let's express a 16-digit decimal number, x as:
x = x_hi * 1e8 + x_lo; // this is pseudocode, not real C
where x_hi is the 8 most-significant decimal digits, and x_lo the least-significant. The modulus of x can then be expressed as:
mod(x) = mod((mod(x_hi) * mod(1e8) + mod(x_lo));
where mod(1e8) is a constant which you can precalculate.
All of this can be done in integer arithmetic.
I could actually use a comment that was deleted right after (wonder why), that said:
modulus = a - a/b * b;
I've made a cast in the division to unsigned long long.
Now... I was a bit disappointed, because in my problem I thought I could keep raising the number of characters of the word with no problem. Nevertheless, I've started to get size issues at the n.ยบ of chars = 7. Why? 95^7 starts to give huge numbers.
I was hoping to get the possibility to write a word like "my cat is so fat I 1234r5s" and calculate the index of this, but this word has almost 30 characters:
95^26 = 2635200944657423647039506726457895338535308837890625 combinations.
Anyway, thanks for the answer.
I'm trying to read in two numbers, and display the absolute difference between them. The numbers get ridiculously large, so I had to switch from LONG to LONG DOUBLE and just display them with 0 precision on the decimal. My issue is that with the number listed in the subject, when I scan it into a long double from a string's c_str either in the scan the last digit is being dropped, or more likely the display of the long double is dropping it.
9223372036854775807 - 1 should be 9223372036854775806 but instead it's displaying 9223372036854775800, and when I stop to inspect the long double with the 9223372036854775807 in it, it just shows me "9.2233720368547758e+018"
I would blame this all on a 2 bit processor, but it seems on a 64 bit it's still printing the wrong answer. Has anyone got any way to preserve the entire number?
my includes are stripped of characters that seemed to be messing with the html parser.
#include iostream
#include string
#include math.h
using namespace std;
int main () {
string line;
std::getline(std::cin, line);
while ( std::cin )
{
long double n, m, o;
sscanf ((char *)line.c_str(),"%Lf %Lf",&n, &m);
if(n>=m)
{
o = n - m;
}
else
{
o = m-n;
}
char buffer[100000];
sprintf( buffer , "%0.0Lf\0", o);
cout << buffer << endl;
std::getline(std::cin, line);
}
return 0;
}
I would stop using long double and use long long if your compiler supports it. You said you had previously been using long so I don't think you were storing fractional parts; if that is correct, then long long would be what you want, not long double. I tested your code with long long on MSVC++ 2010 and it gave the expected output.
And as Mysticial noted, double is the same as long double on many compilers today.
long double is not required to provide more precision than double. However, even if it does, you have to tell the compiler that the literal is a long double. Without a decimal point, the compiler will assume 9223372036854775807 is some kind of integer. So you need to write it as 9223372036854775807.0L.
And again, the compiler doesn't have to give you more precision than a double. So don't be too surprised if you don't get any added precision.
After accept answer.
Floating point numbers have finite precision.
In <cfloat> is LDBL_DIG. This is the number of significant decimal digits that code may read text into a long double and will always print the same digits out again.
The is specified to be at least 10 and is often 15+. 9223372036854775807, with its 18 significant decimal digits certainly exceeds your system's value of LDBL_DIG.
Switching to integer math has a far more limited range. long may not work as LONG_MAX may be as small as 2147483647. Better to use long long which can cope with numbers up to at least 9223372036854775807 - just big enough.
I am attempting to convert base 16 to base 36. I'm taking md5 hashes and making them have all 0-9a-z.
I searched around and didn't find anything good. Any suggestions for converting hexadecimal to hexatridecimal in c++? Do you guys know any good libraries for doing it?
I assume the tricky part you're struggling with is the conversion to Rad36, not getting a integral value from a hex number represented as a string. So, here is a function which takes an unsigned __int64, converts it to Radix 36, and returns a string with the converted value.
string rad36(unsigned __int64 v)
{
string retval;
while( v > 0 )
{
unsigned m = v%36;
if( m <= 9 )
retval.insert(0,1,'0'+m);
else
retval.insert(0,1,'A'+m-10);
v /= 36;
}
return retval;
}
The basic solution is to convert your 128-bit number to a (large) integer, then subsequently perform modulus and divide operations by 36.
However, if you're OK with wasting a couple of bits, why not convert to base 32 to make things easier? Then you can do everything with shifting and masking.