converting number characters in a char array to binary - c++

char *toBin(unsigned long long num)
{
char s[9999];
const int size= 9999;
char *temp = new char[size];
int i, j;
int binBase = 2;
for(i=0; num!= 0; i++)
{
s[i] = num % binBase + '0';
num /= binBase;
}//get backwards binary
for(j=0; i>=0; j++)
{
i--;
temp[j]=s[i];
}//reverse binary sequence
//increments one more so need to decrement
temp[--j] = '\0';
return temp;
delete temp;
}
If I had "82" in a char array, I first converted the "82" to the decimal 82 and gave 82 to the function above to convert to binary. This only works within a certain limit of digits.
I think my problem is that unsigned long long can only hold a certain amount of digits so when it exceeds that limit, some random stuff sent to the function, which prints out the wrong binary.
The above function converts a unsigned long long num to binary. I realized that a better approach would be to look at each character in the char array, rather than converting it to a number first, and and use those values to convert to binary. However, I'm having a hard time trying to put it to code. Any suggestions or help would be appreciated.

the GNU Multiple Precision (GMP) library has the functionality to print any size number in any base. The following is an example.
#include <iostream>
#include <gmpxx>
int main()
{
std::string numstr = "1234123412341234123412341234";
// initialize mpz_class to have numstr in it (given in base 10)
mpz_class bigint(numstr, 10);
// convert to binary (base 2)
std::string binstr = bigint.get_str(2);
std::cout << numstr << " -> " << binstr << std::endl;
return 0;
}
output of program
1234123412341234123412341234 -> 111111110011010111110011000011110100100000101001110100011000000101000011000000000111110010

Allocating an array of 9999 char on the stack is ill-advised because it might be too big for your platform. Anyway, you can easily calculate the maximum number of digits (+terminator) needed: CHAR_BIT*sizeof num+1.
Also, there is no need to allocate an equal amount on the heap.
Do not be afraid of pointers:
Init a pointer to the last byte
Set that to zero
Add all digits beginning with the smallest (at least one, even if the number is 0).
Return a copy of the finished number.

Related

Why is my answer off for certain values of binary representation provided?

The question basically asks us to convert the input binary string (only 1 and 0 provided).
Input format is as follows (each separate point is a new line):
Number of test cases
2N lines with: Length of binary string, Binary string on each alternative line
Output is to return the decimal conversion of the string.
My code:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int t;
cin >> t;
while(t--){
int len;
cin >> len;
long long num = 0;
while(len--){
char digit;
cin >> digit;
num += (digit-'0')*pow(2,len);
}
cout << num << endl;
}
return 0;
}
Ik there are other methods to go about this problem, but i want to know whats the problem in mine. Inputting certain values like '10001011111110111010111011010011011011110001011000011101' gives an answer '39401750052935200' when the correct value is '39401750052935197'.
Other examples of wrong output:
269908306298371776 (correct = 269908306298371795)
1152921504606846976 (correct = 1152921504606846975)
My code runs correct for all smaller values of binary input (of length maybe less than 50). Why does it fail for such larger values by such a small margin?
runs correct for all smaller values of binary input (of length maybe less than 50).
num += (digit-'0')*pow(2,len); is like
num = num + (digit-'0')*pow(2,len);
and the addition is done using double math with its 53-ish bit precision infected by pow().
Instead only use integer math:
unsigned long long num = 0;
...
num = num*2 + (digit-'0');

Separating digits of integer using pointers

I have an integer(i) occupying 4 bytes and i am assuming that it is stored in the memory like this, with starting address as 1000,
If i write int*p=&i;
p now stores the starting address which is 1000 here.
if i increment p it points to the address 1004.
Is there any way to traverse the address 1000, 1001, 1002 and 1003 so that i can separate and print the digits 1 ,5,2,6 using pointers?
Please help..... :( (newbie)
My assumption of storage maybe wrong Can anyone please help me correct it? :(
EDIT 1
According to the answer given by Mohit Jain below and suggestions by others,
unsigned char *cp = reinterpret_cast<unsigned char *>(&i);
for(size_t idx = 0; idx < sizeof i; ++idx) {
cout << static_cast<int>(cp[idx]);
}
I am getting the answer as
246 5 0 0 .
I realized that the way I was assuming the memory structure was wrong,
So is there no way to get the actual digits using pointers??
An int with the value 1526 will not normally be stored as four bytes with the values 1, 5, 2 and 6.
Instead, it'll be stored in binary. Assuming a little-endian machine, the bytes will have the values: 0, 0, 5, 246 (and if it's big-endian, you'll get the same values in the reverse order). The reason for those numbers is that it can store values from 0 to 255 in each byte. Therefore, it's stored as 5 * 256 + 246. When dealing with values in memory like this, it's often convenient (and quite common) to use hexadecimal instead of decimal, in which case you'd be looking at it as 0x05F6.
The usual way to get decimal digits involves more math than pointers. For example, the least significant digit will be the remainder after dividing the value by 10.
To list the memory contents
Using pointer (endian-ness dependent output)
unsigned char *cp = reinterpret_cast<unsigned char *>(&i);
for(size_t idx = 0; idx < sizeof i; ++idx) {
cout << static_cast<int>(cp[idx]);
}
Without using pointer (endian-ness independent output), because digits are not stored the way you assume.
int copy = i;
unsigned int mask = (1U << CHAR_BIT) - 1U;
for(size_t idx = 0; idx < sizeof i; ++idx) {
cout << (copy & mask);
copy >>= CHAR_BIT;
}
To list the digits
If you want the digits of integer using pointer you should first convert the integer to a string:
std::string digits = std::to_string(i); // You can alternatively use stringstream
char *p = digits.c_str();
for(size_t idx = 0; idx < digits.length(); ++idx) cout << (*p++);
You can cast the pointer to (char *) and increment that pointer to point to beginning of individual bytes. However, your assumption of storage is wrong, so you will not get the digits like that.
As I can see you want to extract each digit of a number.
To achieve it You need to:
get reminder of i divided by 10. Do it like this: const int r = i % 10;
divide i by 10: i /= 10;
if i is not 0, go to 1.
Implementation (not tested) could be like this:
do
{
const int r = i % 10;
// do anything you need with r
i /= 10;
} while (i > 0);
This will give you each digit starting from the less significant.

Conversion from Integer to BCD

I want to convert the integer (whose maximum value can reach to 99999999) in to BCD and store in to array of 4 characters.
Like for example:
Input is : 12345 (Integer)
Output should be = "00012345" in BCD which is stored in to array of 4 characters.
Here 0x00 0x01 0x23 0x45 stored in BCD format.
I tried in the below manner but didnt work
int decNum = 12345;
long aux;
aux = (long)decNum;
cout<<" aux = "<<aux<<endl;
char* str = (char*)& aux;
char output[4];
int len = 0;
int i = 3;
while (len < 8)
{
cout <<"str: " << len << " " << (int)str[len] << endl;
unsigned char temp = str[len]%10;
len++;
cout <<"str: " << len << " " << (int)str[len] << endl;
output[i] = ((str[len]) << 4) | temp;
i--;
len++;
}
Any help will be appreciated
str points actually to a long (probably 4 bytes), but the iteration accesses 8 bytes.
The operation str[len]%10 looks as if you are expecting digits, but there is only binary data. In addition I suspect that i gets negative.
First, don't use C-style casts (like (long)a or (char*)). They are a bad smell. Instead, learn and use C++ style casts (like static_cast<long>(a)), because they point out where you are doing things that are dangeruos, instead of just silently working and causing undefined behavior.
char* str = (char*)& aux; gives you a pointer to the bytes of aux -- it is actually char* str = reinterpret_cast<char*>(&aux);. It does not give you a traditional string with digits in it. sizeof(char) is 1, sizeof(long) is almost certainly 4, so there are only 4 valid bytes in your aux variable. You proceed to try to read 8 of them.
I doubt this is doing what you want it to do. If you want to print out a number into a string, you will have to run actual code, not just reinterpret bits in memory.
std::string s; std::stringstream ss; ss << aux; ss >> s; will create a std::string with the base-10 digits of aux in it.
Then you can look at the characters in s to build your BCD.
This is far from the fastest method, but it at least is close to your original approach.
First of all sorry about the C code, I was deceived since this started as a C questions, porting to C++ should not really be such a big deal.
If you really want it to be in a char array I'll do something like following code, I find useful to still leave the result in a little endian format so I can just cast it to an int for printing out, however that is not strictly necessary:
#include <stdio.h>
typedef struct
{
char value[4];
} BCD_Number;
BCD_Number bin2bcd(int bin_number);
int main(int args, char **argv)
{
BCD_Number bcd_result;
bcd_result = bin2bcd(12345678);
/* Assuming an int is 4 bytes */
printf("result=0x%08x\n", *((int *)bcd_result.value));
}
BCD_Number bin2bcd(int bin_number)
{
BCD_Number bcd_number;
for(int i = 0; i < sizeof(bcd_number.value); i++)
{
bcd_number.value[i] = bin_number % 10;
bin_number /= 10;
bcd_number.value[i] |= bin_number % 10 << 4;
bin_number /= 10;
}
return bcd_number;
}

how do I convert an integer which is defined in an int array to hex?

I have an int array that represents a very large number such as:
// ...
unsigned int n1[200];
// ...
n1 = {1,3,4,6,1,...} ==> means my number is 13461...
How can I convert that large number to its hex value?
So here is my take on the problem:
You have an array of digits.
You want to build an unsigned int from this array of digits.
The array of digits could be either HEX digits, or DECIMAL digits.
To build this unsigned long long, assuming an array of DECIMAL digits:
unsigned long long myNum = 0;
unsigned int n1[200];
for (int i=0; i < n1.length ; i++ ){
myNum += pow(10,i) * n1[n1.length - i];
}
To build this unsigned long long, assuming an array of HEX digits:
for (int i=0; i < n1.length ; i++ ){
myNum += pow(16,i)* n1[n1.length - i];
}
(Notice the base 16)
Disclaimer: limited to exactly 16 digits MAX stored in your array. After that you will overrun the buffer
If it is just a matter of DISLAYING the number in the correct format...
Well, an int is an int is an int... (in memory).
There are 10 fingers on my hands whether or not I call that number 10, or A.
If you want to format the number for DISPLAY in hex, then try something like:
unsigned int i = 10;
//OR
unsigned int i = 0xA;
printf("My number in hex: %x", i);
printf("My number in decimal: %d", i);
I'm unsure if you want the hexadecimal represented as a string. If that's
the case, here's some code:
#include <iostream>
#include <stack>
using namespace std;
string toHexa(int num){
string digit = "0123456789ABCDEF", numStr = "";
stack<char> s;
do {
s.push(digit[num%16]);
num /= 16;
} while (num != 0);
while (!s.empty()){
numStr += s.top();
s.pop();
}
return numStr;
}
int main(){
int num = 235; // EB in hexa
cout << num << " to hexadecimal: " << toHexa(num) << endl;
return 0;
}
You could use the GMP library to make this relatively straightforward.
Use basic_stringstream<unsigned int> to wrap your array.
Use operator << to read it into a mpz_t variable.
Create another basic_stringstream<unsigned int> for your result.
Use std::hex and operator >> to write the variable back out in hexadecimal.
That would work on ASCII digits, but yours aren't. You can still use GMP, but you'll want to use the mpn_get_str and mpn_set_str functions instead. You'll need to copy your digits into an unsigned char[] and then you can specify the base for conversion to mp_limb_t and back to a string of digits.

How to convert an int to a binary string representation in C++

I have an int that I want to store as a binary string representation. How can this be done?
Try this:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<32> x(23456);
std::cout << x << "\n";
// If you don't want a variable just create a temporary.
std::cout << std::bitset<32>(23456) << "\n";
}
I have an int that I want to first convert to a binary number.
What exactly does that mean? There is no type "binary number". Well, an int is already represented in binary form internally unless you're using a very strange computer, but that's an implementation detail -- conceptually, it is just an integral number.
Each time you print a number to the screen, it must be converted to a string of characters. It just so happens that most I/O systems chose a decimal representation for this process so that humans have an easier time. But there is nothing inherently decimal about int.
Anyway, to generate a base b representation of an integral number x, simply follow this algorithm:
initialize s with the empty string
m = x % b
x = x / b
Convert m into a digit, d.
Append d on s.
If x is not zero, goto step 2.
Reverse s
Step 4 is easy if b <= 10 and your computer uses a character encoding where the digits 0-9 are contiguous, because then it's simply d = '0' + m. Otherwise, you need a lookup table.
Steps 5 and 7 can be simplified to append d on the left of s if you know ahead of time how much space you will need and start from the right end in the string.
In the case of b == 2 (e.g. binary representation), step 2 can be simplified to m = x & 1, and step 3 can be simplified to x = x >> 1.
Solution with reverse:
#include <string>
#include <algorithm>
std::string binary(unsigned x)
{
std::string s;
do
{
s.push_back('0' + (x & 1));
} while (x >>= 1);
std::reverse(s.begin(), s.end());
return s;
}
Solution without reverse:
#include <string>
std::string binary(unsigned x)
{
// Warning: this breaks for numbers with more than 64 bits
char buffer[64];
char* p = buffer + 64;
do
{
*--p = '0' + (x & 1);
} while (x >>= 1);
return std::string(p, buffer + 64);
}
AND the number with 100000..., then 010000..., 0010000..., etc. Each time, if the result is 0, put a '0' in a char array, otherwise put a '1'.
int numberOfBits = sizeof(int) * 8;
char binary[numberOfBits + 1];
int decimal = 29;
for(int i = 0; i < numberOfBits; ++i) {
if ((decimal & (0x80000000 >> i)) == 0) {
binary[i] = '0';
} else {
binary[i] = '1';
}
}
binary[numberOfBits] = '\0';
string binaryString(binary);
http://www.phanderson.com/printer/bin_disp.html is a good example.
The basic principle of a simple approach:
Loop until the # is 0
& (bitwise and) the # with 1. Print the result (1 or 0) to the end of string buffer.
Shift the # by 1 bit using >>=.
Repeat loop
Print reversed string buffer
To avoid reversing the string or needing to limit yourself to #s fitting the buffer string length, you can:
Compute ceiling(log2(N)) - say L
Compute mask = 2^L
Loop until mask == 0:
& (bitwise and) the mask with the #. Print the result (1 or 0).
number &= (mask-1)
mask >>= 1 (divide by 2)
I assume this is related to your other question on extensible hashing.
First define some mnemonics for your bits:
const int FIRST_BIT = 0x1;
const int SECOND_BIT = 0x2;
const int THIRD_BIT = 0x4;
Then you have your number you want to convert to a bit string:
int x = someValue;
You can check if a bit is set by using the logical & operator.
if(x & FIRST_BIT)
{
// The first bit is set.
}
And you can keep an std::string and you add 1 to that string if a bit is set, and you add 0 if the bit is not set. Depending on what order you want the string in you can start with the last bit and move to the first or just first to last.
You can refactor this into a loop and using it for arbitrarily sized numbers by calculating the mnemonic bits above using current_bit_value<<=1 after each iteration.
There isn't a direct function, you can just walk along the bits of the int (hint see >> ) and insert a '1' or '0' in the string.
Sounds like a standard interview / homework type question
Use sprintf function to store the formatted output in the string variable, instead of printf for directly printing. Note, however, that these functions only work with C strings, and not C++ strings.
There's a small header only library you can use for this here.
Example:
std::cout << ConvertInteger<Uint32>::ToBinaryString(21);
// Displays "10101"
auto x = ConvertInteger<Int8>::ToBinaryString(21, true);
std::cout << x << "\n"; // displays "00010101"
auto x = ConvertInteger<Uint8>::ToBinaryString(21, true, "0b");
std::cout << x << "\n"; // displays "0b00010101"
Solution without reverse, no additional copy, and with 0-padding:
#include <iostream>
#include <string>
template <short WIDTH>
std::string binary( unsigned x )
{
std::string buffer( WIDTH, '0' );
char *p = &buffer[ WIDTH ];
do {
--p;
if (x & 1) *p = '1';
}
while (x >>= 1);
return buffer;
}
int main()
{
std::cout << "'" << binary<32>(0xf0f0f0f0) << "'" << std::endl;
return 0;
}
This is my best implementation of converting integers(any type) to a std::string. You can remove the template if you are only going to use it for a single integer type. To the best of my knowledge , I think there is a good balance between safety of C++ and cryptic nature of C. Make sure to include the needed headers.
template<typename T>
std::string bstring(T n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}
Use it like so,
std::cout << bstring<size_t>(371) << '\n';
This is the output in my computer(it differs on every computer),
0000000000000000000000000000000000000000000000000000000101110011
Note that the entire binary string is copied and thus the padded zeros which helps to represent the bit size. So the length of the string is the size of size_t in bits.
Lets try a signed integer(negative number),
std::cout << bstring<signed int>(-1) << '\n';
This is the output in my computer(as stated , it differs on every computer),
11111111111111111111111111111111
Note that now the string is smaller , this proves that signed int consumes less space than size_t. As you can see my computer uses the 2's complement method to represent signed integers (negative numbers). You can now see why unsigned short(-1) > signed int(1)
Here is a version made just for signed integers to make this function without templates , i.e use this if you only intend to convert signed integers to string.
std::string bstring(int n){
std::string s;
for(int m = sizeof(n) * 8;m--;){
s.push_back('0'+((n >> m) & 1));
}
return s;
}