Binary to integer, need suggestions on this approach. - c

So I'm working on an assignment where I have to perform different operations but without using the standard arithmetic ones. Part of the assignment is converting the users input as an integer in binary form to the standard readable format.
So if the user inputs 0111, I have to return 7.
My question is, how can I split the input into separate values and then store them in an array? I cannot use the standard operands but I do have functions written for addition, subtraction and multiplication.
So what I'm thinking of doing is setting each value of the integer to an array, then reversing it, and in a while loop converting the values by multiplying the given 0 or 1 by corresponding powers of two and then adding everything up.

Scan it as a string. It has a nice advantage of already being an array:
char input[33];
scanf("%s",input);
that gives you an array of characters. They aren't integer which is probably what you want. You can covert it to an array of integers, one character at a time using character arithmetic:
array[i] = input[i] - '0';
You must stop when input[i] is 0, that is the end of the string. You can reverse the array if you want low order bit first.

Related

How does atof.c work? Subtracting an ASCII zero from an ASCII digit makes it an int? Am I missing something?

So as part of my C classes, for our first homework we are supposed to implement our own atof.c function, and then use it for some tasks. So, being the smart stay-at-home student I am I decided to look at the atof.c source code and adapt it to meet my needs. I think i'm on board with most of the operations that this function does, like counting the digits before and after the decimal point, however there is one line of code that I do not understand. I'm assuming this is the line that actually converts the ASCII digit into a digit of type int. Posting it here:
frac1 = 10*frac1 + (c - '0');
in the source code, c is the digit that they are processing, and frac1 is an int that stores some of the digits from the incoming ASCII string. but why does c- '0' work?? And as a followup, is there another way of achieving the same result?
There is no such thing as "text" in C. Just APIs that happen to treat integer values as text information. char is an integer type, and you can do math with it. Character literals are actually ints in C (in C++ they're char, but they're still usable as numeric values even there).
'0' is a nice way for humans to write "the ordinal value of the character for zero"; in ASCII, that's the number 48. Since the digits appear in order from 0 to 9 in all encodings I'm aware of, you can convert from the ordinal value in the encoding (e.g. ASCII) to actual numeric values by subtracting away '0' to get actual int values from 0 to 9.
You could just as easily subtract 48 directly (when compiled, it would be impossible to tell which option you used; 48 and ASCII '0' are indistinguishable), it would just be less obvious what you were doing to other people reading your source code.
The ASCII value of '0' is the 48'th character in code page 437 (IBM default character set). Similarly, '1' is the 49'th etc. Subtracting '0' instead of a magic number such as 48 is much clearer as far as self-documentation goes.

Algorithm for printing decimal value of a huge(over 128bits) binary number?

TLDR, at the bottom :)
Brief:
I am in a process of creating an basic arithmetic library(addition, subtraction, ...) for handling huge numbers. One of the problem i am facing is printing these huge binary numbers into decimal.
I have huge binary number stored in an array of uint64_t. e.g.
uint64_t a[64] = {0};
Now, the goal is to print the 64*64bits binary number in the console/file as its decimal value.
Initial Work:
To elaborate the problem I want to describe how I printed hex value.
int i;
int s = 1;
a[1] = (uint64_t)0xFF;
for(i = s; i>= 0; i--)
{
printf("0x%08llX, ", a[i]);
}
Output:
0x000000FF, 0x00000000,
Similarly for printing OCT value I can just take LSB 3 bits from a[64], print decimal equivalent of those bits, 3 bits right shift all the bits of a[64] and keep repeating until all the values of a[64] has been printed. (print in revers order to keep first Oct digit on the right)
I can print Hex and Oct value of a binary of unlimited size just by repeating this unit algorithm, but I could not find/develop one for Decimal which I can repeat over and over again to print a[64](or something bigger).
What I have thought of:
My initial idea was to keep subtracting
max_64 =(uint64)10000000000000000000; //(i.e.10^19)
the biggest multiple of 10 inside uint64_t, from a until the value inside a is smaller than max_64 (which is basically equivalent of rem_64 = a%max_64 ) and print the rem_64 value using
printf("%019llu",rem_64);
which is the 1st 19 decimal digits of the number a.
Then do an arithmetic operation similar to (not the code):
a = a/max_64; /* Integer division(no fractional part) to remove right most 19 dec digits from 'a' */
and keep repeating and printing 19 decimal digits. (print in such a way that first found 19 digits are on the right, then next 19 digits on its left and so on...).
The problem is this process is to long and I don't want to use all these to just print the dec value. And was looking for a process which avoids using these huge time consuming arithmetic operations.
What I believe is that there must be a way to print huge size just by repeating an algorithm (similar to how Hex and Oct can be printed) and I hope someone could point me to the right direction.
What my library can do(so far):
Add (Using Full-Adder)
Sub (Using Full-subtractor)
Compare (by comparing array size and comparing array elements)
Div (Integer division, no fractional part)
Modulus (%)
Multiplication (basically adding from several times :( )
I will write code for other operations if needed, but I would like to implement the printing function independent of the library if possible.
Consider the problem like this:
You have been given a binary number X of n bits (1<=n<=64*64) you have to print out X in decimal. You can use existing library if absolutely needed but better if unused.
TLDR:
Any code, reference or unit algorithm which I can repeat for printing decimal value of a binary of too big and/or unknown size would be much helpful. Emphasis on algorithm i.e. I don't need a code if some one could describe a process I will be able to implement it. Thanks in advance.
When faced with such doubts, and given that there are many bigint libraries out there, it is interesting to look into their code. I had a look at Java's BigInteger, which has a toString method, and they do two things:
for small numbers, they bite the bullet and do something similar to what you proposed - straightforward link-by-link base conversion, outputting decimal numbers in each step.
for large numbers, they use the recursive Schönhage algorithm, which they quote in the comments as being referred to in, among other places,
Knuth, Donald, The Art of Computer Programming, Vol. 2, Answers to
Exercises (4.4) Question 14.

How to input 1000 digits of integer

So I am on SPOJ [ C language ] and working out some of the initial problems, therin it says to input a number as large as 500-1000 digits.
What I do is input the data into a character array and store each digit as a character. But now afterwards if I have to do some mathematical computations on the input, I have to consider each input as a character, then subtract 48 from it [ASCII for 0] and then digit by digit work out the problem.
Is there a better way to do this?
The biggest optimization would be to represent the number as a byte array, using base 256, so the number is (using ^ as exponentation):
N = n[0]*256^0 + n[1]*256^1 + n[2]*256^2 + ...
That way you use the least memory.
In real life, you could use GMP, which is an open-source big-numbers library.

String to double saving time conversion in c

I'm working on a benchmarking task for an operation (in C language under Linux) and in this operation we use a conversion from string to double a lot (using atof or sscanf functions) but the problem here is that they gave a relatively large time (145, 270 ns respectively) which is not suitable for the operation. So, Do you know any other conversion mechanism that save time?
I tried to use casting but it gave zero
double d;
char ch[] = "123.154";
d = *((double *) ch);
printf ("%lf\n", d); // result 0 (compiled using gcc)
Regards
atof() and sscanf() are generic methods that accept a huge variety of formats. If you know that the floating point values follow a certain pattern, you can try to optimize the conversion for the expected format. ie. no need to support (+-), no need to support Inf, Nan, or sci-notation (1.3e43) etc.
One can make a look up table that converts 3 characters at once from strings:
table[a*256+b*16+c] = a*100+b*10+c; where one simply concatenates the 4 LSB bits of e.g. string "432"; the hex value of the index would be then 0x432 and the content would be 432.
Casting means changing the interpretation of some binary data. Doubles or floats and integers are not binary compatible (except for the value of (+) 0). However the following cast works to check, if three first characters in a strings are numbers:
char num[]="123.123";
if ((*((int*)num) & 0x00f0f0f0) == 0x00303030) // can use faster conversion
// this means interpreting the pointer to string as a pointer to integer
// and then referencing the contents of the memory _as_ integer (+ some bitmasking)
Further, if the set of floating points is relatively small, or some particular value is very frequent, one might trade space for speed and opt for a hash table. If hash table has a match, one can compare the strings 4 or 8 bytes in parallel to verify (or skip that part, if the input is known to be valid). One can also combine these techniques by hashing the first 4 characters for an initial guess and continue from that next 4 characters at a time.
double d;
char ch[] = "123.154";
d = atof(ch);
printf ("%f\n", d);
Or:
printf ("%s\n", ch);

Recursive binary to decimal function without pow() or loops

I am doing a C course.
I need to do a recursive XOR binary but I have some limitations.
I can't use loop or any math.h functions, nor can I call another function from the XOR function.
This is the function prototype:
int binaryXor(int firstnumber[], int secondnumber[], int length);
where firstnumber and secondnumber are arrays with the same length of 1s and 0s and length is their length.
The function should return the decimal value of the XOR of those two arrays.
Doing the XOR is quite simple, but how can I convert it to decimal with all the limitations?
In order to write a recursive function, with no loops, you need to answer the following question:
"How can I express the answer to my problem in terms of a smaller problem?"
In this case, the problem is that you have length digits to look at, but you're not allowed to loop. So, how do you express an xor of size length in terms of a smaller xor, together with some amount of work that doesn't require a loop?
[Edit: hang on, just looked at your question again, and you say you already have the xor sorted, so I guess you've already done this. In that case my comment above is the only thing you need to know: you're finished. An int in C is not a decimal value, it's just a value. You don't need to convert anything to decimal in order to store or return it in an int.
If you're interested though, I can post code that does convert an int to a decimal value using a recursive function. One simple way is to work out on the way "down" how many digits are required, by comparing with bigger and bigger powers of 10, and then on the way back "up" print the digits out starting from the end.]
This is a standard recursive question. The trick is to realize that the integer value of a a string of 1s and 0s followed by a 1 or 0, is 2 * the integer value of the string plus the value of the digit.
So you will want to do something like
if( length <= 0) return 0;
return 2 * binaryXOR(firstnumber, secondnumber, length - 1) + (firstnumber[length - 1] ^ secondnumber[length - 1]);
A recursive function call can be used in place of a loop.

Resources