Decimal to Binary conversion - I need Help [duplicate] - c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Decimal to Binary conversion
I need to convert a 20digits decimal to binary using C programming. How do I go about it. Really, I am finding it hard. What buffer will I create, because it will be very large, even the calculator can't compute converting 20 digits to Binary.
I need suggestions, links and possibly sample codes.
Thanks.

Do you need to convert a decimal string to a binary string or to a value?
Rule of thumb 10^3 ~= 2^10, therefore 10^20 ~= 2^70 > 64 bits (67 to be accurate).
==> A 64bit integer will not not be enough. You can you a structure with 2 64bit integers (long long in C) or even a 8bit byte for the upper part and 64 for the lower part.
Make sure the lower part is unsigned.
You will need to write code that checks for overflow on lower part and increases upper part when this happens. You will also need to use the long division algorithm once you cross the 64bit line.

What about using a library for extended precision arithmetic? try to give a look at http://gmplib.org/

I don't know if you are trying to convert a string of numerical characters into a really big int, or a really big int into a string of 1s and 0s... but in general, you'll be doing something like this:
for (i = 0; i < digits; i++)
{
bit[i] = (big_number>>i) & 1;
// or, for the other way around
// big_number |= (bit[i] << i);
}
the main problem is that there is no builtin type that can store "big_number". So you'll probably be doing it more like this...
uint8_t big_number[10]; // the big number is stored in 10 bytes.
// (uint8_t is just "unsigned char")
for (block = 0; block < 10; block++)
{
for (i = 0; i < 8; i++)
{
bit[block*8 + i] = (big_number[block]>>i) & 1;
}
}
[edit]
To read an string of numerical characters into an int (without using scanf, or atoi, etc), I would do something like this:
// Supposing I have something like char token[]="23563344324467434533";
int n = strlen(token); // number of digits.
big_number = 0;
for (int i = 0; i < n; i++)
{
big_number += (token[i] - '0') * pow(10, n-i-1);
}
That will work for reading the number, but again, the problem with this is that there is no built-in type to store big_number. You could use a float or a double, and that would get the magnitude of the number correct, but the last few decimal places would be rounded off. If you need perfect precision, you will have to use an arbitrary-precision integer. A google search turns up a few possible libraries to use for that; but I don't have much personal experience with those libraries, so I won't make a recommendation.
Really though, the data type you use depends on what you want to do with the data afterwards. Maybe you need an arbitrary-precision integer, or maybe a double would be exactly what you need; or maybe you can write your own basic data type using the technique I outlined with the blocks of uint8_t, or maybe you're better off just leaving it as a string!

Related

Making a function for finding number of digits

I am currently working on a CS50 course and I am trying to make a function that can give me a number of digits in a number that I put. For example number 10323 will be 5 digits. I wrote a code for this but it seems like it doesn't work for case above 10 digits. Can I know what is wrong with this code?
P.S: CS50 uses modified C language for beginners. The language may look a little different but I think its the math that is the problem here so there should be no much difficulty looking at my code?
int digit(int x) //function gives digit of a number
{
if (x == 0)
{
return 0;
}
else
{
int dig = 0;
int n = 1;
int y;
do
{
y = x / n;
dig ++;
n = expo(10,dig);
}
while (y < 0 || y >= 10);
return dig;
}
}
You didn't supply a definition for the function expo(), so it's not possible to say why the digit() function isn't working.
However, you're working with int variables. The specification of the size of the int type is implementation-dependent. Different compilers can have different sized ints. And even a given compiler can have different sizes depending on compilation options.
If the particular compiler your CS50 class is using has 16-bit ints (not likely these days but theoretically possible), those values will go from 0 (0x0000) up to 32767 (0x7FFF), and then wrap around to -32768 (0x8000) and up to 01 (0xFFFF). So in that case, your digit function would only handle part of the range up to 5 decimal digits.
If your compiler using 32-bit ints, then your ints would go from 0 (0x00000000) up to 2147483647 (0x7FFFFFFF), then wrap around to -2147483648 (0x80000000) and up to -1 (0xFFFFFFFF), thus limited to part of the 10-bit range.
I'm going to go out on a limb and guess that you have 32-bit ints.
You can get an extra bit by using the type unsigned int everywhere that you are saying int. But basically you're going to be limited by the compiler and the implementation.
If you want to get the number of decimal digits in much larger values, you would be well advised to use a string input rather than a numeric input. Then you would just look at the length of the string. For extra credit, you might also strip off leading 0's, maybe drop a leading plus sign, maybe drop commas in the string. And it would be nice to recognize invalid strings with unexpected non-numeric characters. But basically all of this depends on learning those string functions.
"while(input>0)
{
input=input/10;
variable++;
}
printf("%i\n",variable);"
link an input to this.

Why won't these two functions convert decimals to binary (uint8_t)? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have two functions which supposedly can convert decimals to binary, however I can't seem to get them to work if the decimal is above 3 (I get weird negative numbers). I can't fully understand the code in the functions as I've only just started to learn C, however I was hoping if someone could tell me if the functions work, or if I am just not doing something right i.e. should I be using int32_t type as the value to pass into the function?
uint8_t dec_to_bin(int decimal){
int n = decimal, i, j, binno=0,dn;
dn=n;
i=1;
for(j=n;j>0;j=j/2)
{
binno=binno+(n%2)*i;
i=i*10;
n=n/2;
}
return binno;
}
uint8_t dec_to_bin2(int decimal){
long long binaryNumber = 0;
int remainder, i = 1;
while (decimal!=0){
remainder = decimal%2;
decimal /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
Unfortunately I have no way to find out the values of the binary numbers as a uint_8 type as I am doing this on a micro-controller and there is no way to debug or print values anywhere (I have posted numerous threads asking how to do this, with no luck). We have however been provided with another function:
int bin_to_dec(uint64_t binary) {
int result = 0;
for ( int i = 7; i >= 0; i-- ) {
result = result * 10 + ((binary >> i) & 1);
}
return result;
}
This function converts the binary number back to an integer so I can display it on the screen with a library function (the library function can only display integers or strings). If I pass 10 into either of the decimal to binary converter functions, then pass the uint_8 value from either function to the binary to decimal converter and print to the LCD, I get -3110. This should just be 1010.
I'm sorry to say, but your dec_to_bin and dec_to_bin2 functions are meaningless. Throw them away. They might -- might -- have a tiny bit of value as a teaching exercise. But if you're trying to write actual code for a microcontroller to actually do something, you don't need these functions, and you don't want these functions. (Also you need to understand why you don't need these functions.)
The problem is not that they're implemented wrongly. They're fundamentally flawed in their very intent.
These functions seem to convert, for example, the integer 5 to the integer 101, and at first glance that might look like "decimal to binary conversion", but it's not. You've just converted the number five to the number one hundred and one.
Let's look at this a different way. If I say
int i = 17;
and if I then call
printf("%d\n", i);
I see the value "17" printed, as I expect. But I can also call
printf("%x\n", i);
and this prints i's value in hexadecimal, so I see "11". Did I just convert i from decimal to hexadecimal? No, I did not! I took the same number, "seventeen", and I printed it out in two different ways: in decimal, and in hexadecimal.
For all practical purposes, unless you're designing the actual hardware a program will run on, it really doesn't make sense to ask what base a number is stored in. A variable like int i is just a number, an integer. (Deep down inside, of course, on a conventional processor we know it's stored in binary all the time.)
The only time it makes sense to explicitly convert a number to binary is if you want to print it out in a human-readable text representation, in binary. In that case, you're converting from an integer to a string. (The string will consist of the characters '0' and '1'.)
So if you want to write a meaningful decimal-to-binary converter (which will actually be an anything-to-binary converter), either have it print the binary number out to the screen, or store it in a string (an array of characters, or char []).
And if you're in a class where you're being asked to write uint8_t dec_to_bin(int decimal) (or where your instructor is giving you examples of such functions), I can't help you, and I'm afraid you're doomed. Half of what this instructor is teaching you is wrong or badly misleading, will seriously handicap you from ever being a successful C programmer. Of course I can't tell you which half, because I don't know what other lies you're being taught. Good luck -- you'll need it! -- unlearning these false facts later.
I don't know why you're trying to store binary data as base 10 numbers instead of just printing or storing (as a char[]) the bits of an int (get kth bit of n as (n >> k) & 1 then print/store), but I'll assume it's necessary.
Your solution could be prone to overflowing the uint8_t as mentioned in the comments. Even a uint64_t can only hold 19 bits of binary data in the format you're using, less than the 32 of typical ints. The return type of your second function is still uint8_t, this might just be a typo, but it means the internal representation of long long will be implicitly cast on return.
I've written some functions based on yours, but with a little more bit manipulation that work for me.
uint64_t dec_to_bin (int n)
{
uint64_t result = 0;
int k, i;
// 64 bits can only hold 19 (log10(2^64)) bits in this format
for (i = 0, k = n; k && i < 19; i++) {
// Because the loop is limited to 19 we shouldn't need to worry about overflowing
result *= 10;
result += (n >> i) & 1;
k /= 2;
}
return result;
}
int bin_to_dec (uint64_t n)
{
int result = 0;
while (n) {
result <<= 1;
result += n % 2;
n /= 10;
}
return result;
}
I tested your functions on the input 43 on my system and got
43 // Original Input
101011 // dec_to_bin2 with long long return type
10010011 // bin_to_dec
With an appropriately sized output, your dec_to_bin2 function does work as expected.
And my functions:
43 // Original Input
110101 // dec_to_bin
43 // bin_to_dec
The endianness may not be what you're expecting, but that can be changed if necessary.

C: Converting a very large integer into a binary

I am trying to convert decimal Nos. into binary. The code works pretty fine (Windows 7 , 32 bit MS-VS2010):
int main()
{
int k, n;
int binary[100];
printf("Enter the value in decimal \n ");
scanf("%d", &k);
n = (log(k * 1.0) / log(2 * 1.0)) + 1 ; //total no. of binary bits in this decimal
for (int i = n; i > 0; i--)
{
binary[i] = k % 2;
k /= 2;
}
return 0;
}
But the limitation is that it works for Int size values only i.e. 32 bit. I want to modify this code so that it works for 2048 bits (decimal numbers containing 617 digits actually). I am not allowed to use any library.
Can someone give me some pointers how to proceed to tackle this?
Can someone give an example code snippet say for 64 bits ? Then I can use this to extend to higher values.
Update
1-As per suggestions I am trying to use strings. But I am not able to understand how to convert an String into large Int (I cant use stoi() as thsi will convert to 32 bit int , right? ).
2- Secondly I have to find:
log(222121212213212313133123413131313131311313154515441315413451315641314563154134156313461316413415635154613415645156451434)
Is the library function log capable of finding this ? Then what is the solution?
Since you told that you just need some pointers and not the actual answer, here goes:
I am not able to understand how to convert an String into large Int
That's because you can't. If you want to convert a number that huge to a numerical type, in the first place you need such a type that can hold numbers that big. The language doesn't provide you anything more than long long which is usually 128-bits long (i.e. if you can use C99, or just long which is usually lesser than a long long). Since your tutor told you not to use any external library, it's a clear sign that s/he wants you to code the solution using what's available only in the language and perhaps additionally the standard library.
Is the library function log capable of finding this
No, you can't use stoi or log since all of these expect arguments of some arithmetic type, while none of those built-in types are that big to hold numbers this huge. So you've to work completely with strings (i.e. either static or dynamic char buffers).
I understand that you want to use log to deduce the number of digits the binary output would need; but there's another option, which is to not know the number of digits before hand and allocate them dynamically with some upper bound so that you needn't re-allocate them further.
Lets take an example.
Allocate 3 char buffers in, out (length of input) and bin (length of input * 4).
Copy input to in
While in is not "0" or "1" do else goto 12
For each element ch in in do else goto 10
Convert ch to integer i
If is_odd = 1 then i += 10
quot = i / 2
Append quot to out
is_odd = quot % 2; goto 4
If is_odd = 1 append '1' else '0' to bin
Copy out to in, reset out and goto 3
Append in to bin
Print bin in reverse
When you integer divide a number by 2, the quotient would always be less than or equal to the number of digits of the dividend. So you could allocate in and out with the same size as the input and use it for all iterations. For the bin buffer, the knowledge that each decimal digit wouldn't take more than 4 bits (9 takes a nibble, 1001) would help. So if the input is 10 digits, then 10*4 = 40 bytes would be the upper limit needed for bin buffer and 10 bytes would be needed for the in and out buffers.
This is a vague write-up of an algorithm, I hope it conveys the idea. I feel writing code is more easier than writing algorithms properly.
I'm afraid there are no standard types in C that will allow you to store such a big value with 20148 bits... You can try to read the string from console (not converting into int), and then parse the string into "010101...." on your own.
The approach would be like that:
You should go for "dividing" the string by 2 in each step (for each division by 2 you need to divide all digits of the string by 2, and handle special cases like 11 / 2 => 5), and for each step if the value cannot be divided by 2, then you then you can put "1" as another binary digit, otherwise you put "0". This way you gather the digits '0', '1', '0', '1', etc. one by one. Then finally you need to reverse the order of digits. A similar approach implemented in C# you can find here: Decimal to binary conversion in c #
Regarding the update:
Grinding it through WolframAlpha gives:
log(222121212213212313133123413131313131311313154515441315413451315641314563154134156313461316413415635154613415645156451434)
is roughly
274.8056791141317511022806994521207149274321589939103691837589..
Test:
Putting it into exp gives:
2.2212121221321231313312341313131313131131315451544131541.. × 10^119
This raises the question about the precision you need.
Note: I assumed you mean the natural logarithm (base e).

How to store 14.5 trillion and some change in a C floating point type variable

I'm creating a change counter program for my C++ class. The numbers we are using are in the 10s of trillions and I was wondering if there was an easy way to store that into a floating point type variable then cast that into an integer type. It isn't an integer literal, it's accepted as an input and I expect possible change.
Don't use floats. Keep it as an integer and use 64-bit longs. Use "long long" or "int64_t" as the type for storing these integers. The latter can be used by #include <stdint.h>
int main()
{
long long x = 1450000000000LL;
printf("x == %lld\n", x);
return 0;
}
Uhm. No :D
You can however use matrices and write functions for the mathematical operations you need to use. If you're doing a lot or arithmetic with very large numbers, have a look at http://gmplib.org/
If you use floating point math to represent your change counter you'll get in serious troubles. Why? - You are a victim of accuracy problems that lead to problems representing values differing in the 1s, 10s and 100s and so on up to (IIRC) 10^6 of the values. (assuming you are referring to 10^12 version of the term 'trillion'. See H. Schmidt's IEEE 754 Converter page and the Wikipedia article about thisif you want deeper insight into this)
So if you need a precision that goes higher than a several million (and I assume you do), you'll really get in hot water if you use such a beast like floating points. You really need something like the (multiple precision library from GNU in order to be able to calculate the numbers. Of course you are free to implement the same functionality yourself.
In your case mabye a 64-bit integer could do it. (Note that long long is not always 64 bit and nonstandard for C89) Just parse the user input yourself by doing something like this (untested, just to illustrate the idea):
const char input[] = "14.5"
uint64_t result = 0;
uint64_t multiplier = 1000000000000;
unsigned int i = 0;
/* First convert the integer part of the number of your input value.
Could also be done by a library function like strtol or something
like that */
while ((input[i] != '.')
&& (input[i] != '\0'))
{
/* shift the current value by 1 decimal magnitude and add the new 10^0 */
result = (result * 10) + (input[i] - '0');
i++;
}
/* Skip the decimal point */
if (input[i] == '.')
{
i++;
}
/* Add the sub trillions */
while (input[i] != '\0')
{
/* shift the current value by 1 decimal magnitude and add the new 10^0 */
result = (result * 10) + (input[i] - '0');
multiplier /= 10; // as this is just another fraction we have added,
// we reduce the multiplier...
i++:
}
result = result * multiplier;
Of course there are a several exceptions that need to be handled seperatly like overflows of the result or handling non numeric characters properly but as I noted above, the code is only to illustrate the idea.
P.S: In case of signed integers you have to handle the negative sign too of course.

how do we print a number that's greater than 2^32-1 with int and float? (is it even possible?)

how do we print a number that's greater than 2^32-1 with int and float? (is it even possible?)
How does your variable contain a number that is greater than 2^32 - 1? Short answer: It'll probably be a specific data-structure and assorted functions (oh, a class?) that deal with this.
Given this data structure, how do we print it? With BigInteger_Print(BigInteger*) of course :)
Really though, there is no correct answer to this, as printing a number larger than 2^32-1 depends entirely upon how you're storing that number.
More theoretically: suppose you have a very very very large number stored somewhere somehow; if so, I suppose that you are somehow able to do math on that number, otherwise it would be quite pointless storing it.
If you can do math on it, just divide the bignumber by ten (10); store the remainder somewhere. Repeat until the result is smaller than 10. When it's smaller than ten, print it, then print the remainders, from the last to the first. Finish.
You can speed up things by dividing for the largest power of 10 that you are able to print without effort (on 32 bit, 1'000'000'000).
Edit: pseudo code:
#include <stdio.h>
#include <math.h>
#include <math_with_very_very_big_num.h>
int main(int argc, char **argv) {
very_very_big_num bignum = someveryverybignum;
very_very_big_num quot;
int size = (int) floor(vvbn_log10(bignum)) + 1;
char *result = calloc(size, sizeof(char));
int i = 0;
do {
quot = vvbn_divide(bignum, 10);
result[i++] = (char) vvbn_remainder(bignum, 10) + '0';
bignum = quot;
} while (vvbn_greater(bignum, 9));
result[i] = (char) vvbn_to_i(bignum) + '0';
while(i >= 0)
printf("%c", result[i--]);
printf("\n");
}
(I wrote this using long, than translating it with veryverybignum stuff; it worked with long, unluckily I cannot try this version, so please forgive me if I made transation errors...)
If you are talking about int64 types, you can try %I64u, %I64d, %I64x, %llu, %lld
On common hardware, the largest float is (2^128 - 2^104), so if it's smaller than that, you just use %f (or %g or %a) with printf( ).
For int64 types, JustJeff's answer is spot on.
The range of double (%f) extends to nearly 2^1024, which is really quite huge; on Intel hardware, when the long double (%Lf) type corresponds to 80-bit float, the range of that type goes up to 2^16384.
If you need larger numbers than that, you need to use a library (which will likely have its own print routines) or roll your own representation and provide your own printing support.

Resources