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.
Related
I am currently working on an arbitrary size integer library for learning purposes.
Each number is represented as uint32_t *number_segments.
I have functional arithmetic operations, and the ability to print the raw bits of my number.
However, I have struggled to find any information on how I could convert my arbitrarily long array of uint32 into the correct, and also arbitrarily long base 10 representation as a string.
Essentially I need a function along the lines of:
std::string uint32_array_to_string(uint32_t *n, size_t n_length);
Any pointers in the right direction would be greatly appreciated, thank you.
You do it the same way as you do with a single uint64_t except on a larger scale (bringing this into modern c++ is left for the reader):
char * to_str(uint64_t x) {
static char buf[23] = {0}; // leave space for a minus sign added by the caller
char *p = &buf[22];
do {
*--p = '0' + (x % 10);
x /= 10;
} while(x > 0);
return p;
}
The function fills a buffer from the end with the lowest digits and divides the number by 10 in each step and then returns a pointer to the first digit.
Now with big nums you can't use a static buffer but have to adjust the buffer size to the size of your number. You probably want to return a std::string and creating the number in reverse and then copying it into a result string is the way to go. You also have to deal with negative numbers.
Since a long division of a big number is expensive you probably don't want to divide by 10 in the loop. Rather divide by 1'000'000'000 and convert the remainder into 9 digits. This should be the largest power of 10 you can do long division by a single integer, not bigum / bignum. Might be you can only do 10'000 if you don't use uint64_t in the division.
I have a big hexadecimal number, for example CD4A0619FB0907BC00000 (25!) or any other number like this. Now, using standard C/C++ code only (no libraries like Boost), I want to convert this number to the decimal number 15511210043330985984000000. Unfortunately, it's too big for a 64 bit integer (like long long) and I don't want to use any floating point data types either. If this is possible at all, how can you do this?
Assuming you don't want to use any of resources that might fit your description "libraries like Boost". The simple answer is to write your own subset of one, with just the operations you need.
If 32 hex digits is enough, then simplest would be to create your own 128 bit unsigned int and code a divide by 10 function (producing quotient and remainder) for that 128-bit int. You really don't need any other functions and divide by 10 is pretty easy. Converting up to 32 hex digits to 128 bit int is trivial and generating decimal output from a series of divide by ten is trivial.
If you want essentially unlimited size, then it is likely simpler to represent a decimal number as a string of digits and write a routine to multiply that by 16 and add in another digit. That would never be the efficient solution, just likely easier to code for your purpose and unlimited size.
vector<unsigned int> bin2dec(vector<unsigned int> binary)
{
vector<unsigned int> decimal;
bool all_zero = false;
// binary[i]: stores 8-bit of the nubmer.
// Ex. 258 = 0x102 => binary[0] = 0x2, binary[1] = 0x1.
while (!all_zero) {
all_zero = true;
for (int i = binary.size() - 1; i >= 0; i--) {
int q = binary[i] / 10;
int r = binary[i] % 10;
binary[i] = q;
if (i > 0) {
binary[i-1] += (r << 8);
} else {
decimal.insert(decimal.begin(), r);
}
if (q != 0) {
all_zero = false;
}
}
}
// each element stands for one digit of the decimal number.
// Ex. 258 => decimal[0] = 2, decimal[1] = 5, decimal[2] = 8.
return decimal;
}
If you don't want to use external libraries then you will have to implement a arbitary-precision integer type yourself. See this question for ideas on how to do this. You will also need a function/constructor for converting hexadecimal strings to your new type. See this question for ideas on how to do this.
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' ;
}
I have a little problem when assigning a result to a variable, this is happening the first time to me now. I call Convert() with "aaa" as a parameter, here is my output:
aaa
**676** *(value from cout)* = 26^(3-1)*1 **675** *(value of the variable)*
+26 = 26^(3-2)*1 700
+1 = 26^(3-3)*1 701
701
And here the code:
string alphabet="abcdefghijklmnopqrstuvwxyz";
unsigned long long Convert(string &str){
unsigned long long wvalue=0;
for(int i=0;i<str.size();++i){
size_t found=alphabet.find(str[i]);
if(found==string::npos)
cout<<"Please enter only lowercase letters of the english alphabet!"<<endl;
unsigned long long add=((found+1)*pow(26,(str.size()-(i+1))));
wvalue+=add;
if(i>0)cout<<"+";
cout<<"\t"<<((found+1)*pow(26,(str.size()-(i+1))))<<" = "<<"26^("<<str.size()<<"-"<<(i+1) <<")*"<<(found+1)<<"\t"<<wvalue<<endl;
}
return wvalue;
}
Chances are I'm missing something awfully obvious, but I cannot figure it out.
((found+1)*pow(26,(str.size()-(i+1))))
is doing the calculation, and it is doing as it is supposed to, the result within the cout-statment is correct. But the variable is substracted by 1 in the first two assignments.
pow is a floating-point function. It takes and returns floating point numbers. Assigning a floating-point number to an integer variable truncates it to an integer number, so it might have been 675.9999999 just before the assignment, which will turn into 675 when assigned to the integer variable add.
cout also rounds floating-point numbers, depending on the configuration for example to 6 significant digits. 676.0 is a better approximation than 675.999, so you see 676 in the output.
Since you don't want to calculate with real numbers but only with integral numbers, you better stay with integral functions. To take 26 to the power of n, better use multiplication n times. Since you already use a loop, and like to have the next power of 26 for every character, the best is to add a variable in which you keep the current power value, like this:
unsigned long long currentFactor = 1;
for (...) {
...
unsigned long long add = currentFactor * (found+1);
wvalue += add;
currentFactor *= 26;
}
Also note that you don't have to find the character in an alphabet string. You can also just use character arithmetic to do this:
int charNumber(char c) {
if (c >= 'a' && c <= 'z')
return c - 'a'; // calculate the position of c relative to 'a'
else
return -1; // error
}
How to convert string (22.123) format number into float variable format without using any API in c++. This is just to understand more about the inside coding.. thnx
something like:
double string_to_double(std::string s)
{
int p = 0;
int p_dec = s.length();
double val = 0;
for (int i=0; i<s.length(); ++i)
{
double digit = (double)(s[i] - '0');
if (s[i] == '.') { p_dec = p; }
else { val += digit*powf(10,p--); }
}
val /= powf(10, p_dec);
}
Basic algorithm, assuming no input in the form 1.2e-4:
(1) Read an integer before the dot. If the number of digits is > 16 (normal precision of double), convert that integer into floating point directly and return.
(2) Read an at most 16 digits dot as an integer. Compute (that integer) ÷ 10digits read. Sum up this with the integer in step (1) and return.
This only involve 2 floating point operation: one + and one ÷, and a bunch of integer arithmetics. The advantage over multiplications and divisions by powers of 10 is that the error won't accumulate unnecessarily.
(To read 16-digit integers you need a 64-bit int.)
In reality, you should use sscanf(str, "%lf", ...), std::istringstream, or boost::lexical_cast<double>.
go over the number digit by digit by using a bunch of multiplications and divisions by powers of 10 and construct the string character by character.
If you just want an idea of how to do it, the other answer, if you want an accurate result, the problem is not so simple and you should refer to the literature on the subject. An example: ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.ps
I'm pretty sure that the Plauger Standard C Library book has a disc with the source of strtod.
http://www.amazon.co.uk/Standard-C-Library-P-J-Plauger/dp/0131315099
and there are online versions too:
http://www.google.co.uk/search?hl=en&client=firefox-a&hs=IvI&rls=org.mozilla%3Aen-GB%3Aofficial&q=strtod+source+code