We were assigned a task to convert octal numbers to binary and decimal. Smaller numbers works just fine but it then gives a different output at a higher input. Here is the code:
#include <stdio.h>
void main() {
unsigned long n, g, ans = 1, r = 0, dec = 0, place = 1, bin = 0;
printf("Conversion: Octal to decimal and binary.\n");
printf("Enter number: ");
scanf("%lu", &n);
printf("%lu is ", n);
for (g = n; g != 0; ans = ans * 8) {
r = g % 10;
dec = dec + r * ans;
g = g / 10;
}
printf("%lu in Decimal Form. \n", dec);
printf("%lu is ", n);
for (; dec != 0; place = place * 10) {
r = dec % 2;
bin = bin + (r * place);
dec = dec / 2;
}
printf("%lu in Binary Form.\n", bin);
}
We were only required to use limited data types and control structures. No arrays, strings, functions or such.
The input in our teacher's test case is 575360400 which must print an output of 101111101011110000100000000 in binary and 100000000 in decimal. But the output in binary is 14184298036271661312. I used unsigned long already and it just won't work.
I don't know how this is possible with the given restrictions and your comments and answers will be really much of a help.
Smaller numbers works just fine but it then gives a different output at a higher input.
Overflow
Input "575360400" (base 8) converts to a 27-bit value. For place = place * 10 ... bin = bin + (r * place); to work, bin needs to be a 90-bit unsigned long. unsigned long is certainly 64-bit or less.
OP needs a new approach.
I'd start with reading the octal input with scanf("%lo", &n); and printing the decimal with printf("%lu\n", n);.
To print in binary, without arrays, functions, etc., consider a mask, first with the most significant bit, that is shifted right each iteration.
bool significant_digit = false;
// Form 0b1000...0000
// 0b1111... - 0b01111..
unsigned long mask = ULONG_MAX - ULONG_MAX/2;
while (mask) {
bool bit = mask & n;
if (bit || significant_digit || mask == 1) {
significant_digit = true;
printf("%d", bit);
}
mask >>= 1;
}
printf("\n", bit);
}
Better approaches exist. Yet with OP's artificial limitations: "No arrays, strings, functions or such.", I opted for something illustrative and simple.
Or wait until 2023
C2x expected to support printf("%lb\n", n);. Just ask the professor for an extension 😉.
Related
I have a text file with a list of decimals. I need to print to another file a list of decimals which are the base 10 of the binary mirrors of the original numbers. Currently I'm doing it like this (where each step is one function):
decimal strings -> number array -> binary strings -> base 10 of binary mirror
Is there a much shorter number of steps I could have taken that I failed to see or does this make sense?
Assuming you have a 32-bit integer, you can revert the bits by doing:
#include <stdio.h>
void printBinary(int x)
{
int m = 0x80000000;
while(m)
{
printf("%d", (m & x) ? 1 : 0);
m = m >> 1;
m = m & 0x7fffffff;
}
printf("\n");
}
int binaryReverse(int x)
{
int i = 0;
int t = 0;
int m = 0x80000000;
while(m)
{
if (m & x)
{
t = t | (1 << i);
}
++i;
m = m >> 1;
m = m & 0x7fffffff;
}
return t;
}
int main(void) {
int x = 19088743;
printf("%u\n",x);
printBinary(x);
int y = binaryReverse(x);
printf("%u\n",y);
printBinary(y);
return 0;
}
Output:
19088743
00000001001000110100010101100111
3869426816
11100110101000101100010010000000
You don't need to convert to strings of ASCII "1"s and "0"s (what I assume is meant by "binary strings") for that-- you can use bitwise operators. You can omit the "binary strings" step.
Note that "binary mirror" is an unclear term, however googling it may lead you to find the real name for what you actually want to do.
I would like to produce a function which takes an integer x and char array in, and returns a string x steps into the sequence.
For example, consider the alphabet 'abc', which would produce the strings a, b, c, aa, ab, ac, ba, bb, bc, ca, cb, cc, aaa, aab... If the index 0 was passed in, I would expect the output to be 'a'; likewise, if the index 34 was passed in, I would expect the output 'cbb'.
For the alphabet '0123456789' I would expect the strings 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11...
I have written the following thus far, but am getting stuck on cases 21-23, 33-35, 45-47 where the behaviour deviates and I've been staring at this for a number of hours now without a pattern jumping out at me (with respect to the alphabet size and index). At first I didn't notice the issue, using a larger sized alphabet until it created bigger issues further in my program.
I'm not going to pretend the code below is in anyway elegant, following good practice, nor optimised - at this stage I really just want to understand the correct implementation of this pattern and have been changing things all over the place to attempt to resolve the issue. Apologies in advance if the variable names are confusing. Also, is this a common pattern/issue? I have tried to search for similar algorithms but have been unable to find anything with the terms that come to mind.
unsigned long power(int num, int exp)
{
int i;
unsigned long ret = num;
if (exp == 0) return 1;
for (i = 1; i < exp; i++)
{
ret *= num;
}
return ret;
}
unsigned long sumsqr(int base, int exp)
{
unsigned long sum;
for (sum = 0; exp > 0; exp--)
{
sum += power(base, exp);
}
return sum;
}
char * generateStringT(unsigned long index, char * charmap)
{
unsigned long scaler;
unsigned long remainder;
unsigned long divisor;
int base;
int exponent;
int factor;
char * buffer;
char * string;
int i;
buffer = malloc(sizeof(char) * 100);
i = 0;
base = strlen(charmap);
exponent = 0;
divisor = 0;
remainder = index;
while(sumsqr(base, exponent) <= index)
{
exponent++;
}
exponent--;
factor = exponent;
while(factor >= 0)
{
divisor = power(base, factor);
if ((factor > 1) && (exponent > 0))
divisor += power(base, factor-1);
scaler = remainder/divisor;
remainder = remainder - scaler * divisor;
printf("%lu,", scaler);
if ((factor == exponent) && (exponent > 0)) scaler--;
buffer[i++] = charmap[scaler];
factor--;
}
buffer[i++] = '\0';
string = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(string, buffer);
free(buffer);
return string;
}
What you are trying to do there looks like a base conversion, but actually is slightly different. Any number in any base can be thought as if they have infinitely many preceding zeros (or whatever the least significant digit is at that base) behind the represented number. This is not true in your case.
In your case, you lay importance to the amount of digits on the number you represent, making it slightly more complicated to index them. With bases in maths, it is easy to calculate the index of a represented number in any base b; that is, sum of the rank times the base raised to the power of order for each digit. In your case, the index builds up an additional sum_{k = 1}^{amount.of.digits.on.our.number - 1} base^k. If we subtract that addition from the index, our task becomes rather easy.
That addition can be calculated using your sumsqr function.
Here, I have changed your code just a little, with comments at where I've done changes, which is able to resolve many, just like you expect it to:
// added this
remainder -= sumsqr(base, exponent);
while (factor >= 0)
{
divisor = power(base, factor);
// commented this out
// if ((factor > 1) && (exponent > 0))
// divisor += power(base, factor - 1);
scaler = remainder/divisor;
remainder = remainder - scaler * divisor;
printf("%lu,", scaler);
// commented this out
// if ((factor == exponent) && (exponent > 0))
// scaler--;
buffer[i++] = charmap[scaler];
factor--;
}
I am not exactly sure what you were trying to do with the parts I've commented out. My guess is that you were trying to increase the divisor by that amount of difference I've talked previously, instead of decreasing the index or remainder by that amount.
Hope this helps in any way.
Not a fix (at a glance, your code uses a similar idea -- but more complicated!), but this is the code I used to convert an integer index to an a,b,c-format page number:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *number_alpha (char *dest, int value, char *base)
{
char *ddest = dest, *startdest = dest, swop;
if (value < 0)
{
value = -value;
*dest = '-';
startdest++;
ddest++;
}
value++;
do
{
*ddest = base[((value-1) % strlen(base))];
ddest++;
value = (value-1)/strlen(base);
} while (value > 0);
*ddest = 0;
ddest--;
while (ddest > startdest)
{
swop = *ddest;
*ddest = *startdest;
*startdest = swop;
startdest++;
ddest--;
}
return dest;
}
int main (int argc, char **argv)
{
int number;
char result[256];
if (argc != 3)
{
printf ("usage: [number] [string]\n");
return -1;
}
number = strtol (argv[1], NULL, 10);
number_alpha (result, number, argv[2]);
printf ("%d in 'base' %s yields %s\n", number, argv[2], result);
return 0;
}
It is very similar to the common task 'convert an integer to decimal notation'. By removing the value++ and changing (value-1) twice to just value in number_alpha, you get a bog-standard Int-To-Ascii routine. This one is special because the "wrap" occurs at a different place: for a base of 0123456789, incrementing 9 shows 00, not 10.
Sample outputs:
0 in 'base' abc yields a
34 in 'base' abc yields cbb
34 in 'base' 0123456789 yields 24
-34 in 'base' abc yields -cbb
9 in 'base' 0123456789 yields 9
10 in 'base' 0123456789 yields 00
--
See Translate a column index into an Excel Column Name for a couple of implementations in other languages. They seem to focus on recursive solutions, where mine is linear (for better or worse).
I have written a program in C to convert a floating point number represented in binary (1101.11) into a decimal (13.75).
However, I cannot seem to get the correct value out of the algorithm.
What is the correct method for converting a binary floating point number into a decimal?
I am using Dev CPP compiler (32 bit). The algorithm is defined below:
void b2d(double p, double q )
{
double rem, dec=0, main, f, i, t=0;
/* integer part operation */
while ( p >= 1 )
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
dec = dec + rem * pow(2, t);
t++;
}
/* fractional part operation */
t = 1; //assigning '1' to use 't' in new operation
while( q > 0 )
{
main = q * 10;
q = modf(main, &i); //extration of frational part(q) and integer part(i)
dec = dec+i*pow(2, -t);
t++;
}
printf("\nthe decimal value=%lf\n",dec); //prints the final output
}
int main()
{
double bin, a, f;
printf("Enter binary number to convert:\n");
scanf("%lf",&bin);
/* separation of integer part and decimal part */
a = (int)bin;
f = bin - a;
b2d(a, f); // function calling for conversion
getch();
return 0;
}
You are not, as you believe, reading "1101.11" as a floating point number represented in binary. You are reading it as a base-10 floating point number converted into an IEEE double-precision floating-point value, and then trying to change the base.
The inherent imprecision of this intermediate step is the reason for your problem.
A better approach, as suggested by Vicky, is to:
read "1101.11" as a string or line of text
convert the whole and fractional parts (whole=b1101=13 and numerator=b11=3, denominator=4)
re-combine these into whole + numerator/denominator = 13.75
Solution
The following will work as expected:
Output:
➤ gcc bin2dec.c -lm -o bin2dec && bin2dec
1101.11 -> 13.750000
1101 -> 13.000000
1101. -> 13.000000
.11 -> 0.750000
Code (bin2dec.c):
#include <stdio.h>
#include <math.h>
double convert(const char binary[]){
int bi,i;
int len = 0;
int dot = -1;
double result = 0;
for(bi = 0; binary[bi] != '\0'; bi++){
if(binary[bi] == '.'){
dot = bi;
}
len++;
}
if(dot == -1)
dot=len;
for(i = dot; i >= 0 ; i--){
if (binary[i] == '1'){
result += (double) pow(2,(dot-i-1));
}
}
for(i=dot; binary[i] != '\0'; i++){
if (binary[i] == '1'){
result += 1.0/(double) pow(2.0,(double)(i-dot));
}
}
return result;
}
int main()
{
char bin[] = "1101.11";
char bin1[] = "1101";
char bin2[] = "1101.";
char bin3[] = ".11";
printf("%s -> %f\n",bin, convert(bin));
printf("%s -> %f\n",bin1, convert(bin1));
printf("%s -> %f\n",bin2, convert(bin2));
printf("%s -> %f\n",bin3, convert(bin3));
return 0;
}
Explanation
The above code works by first finding the index of the decimal point in the number.
Once that is known, it walks the string both backwards and forwards from this index, adding the appropriate value to the result variable.
The first loop walks backwards from the decimal point and accumulates the powers of 2 if the character is 1. It takes the distance from the decimal point as the power of two, minus one for the indexing to be correct. Ie, it accumulates :
pow(2,<distance-from-decimal-point>)
The loop stops when the index reaches the beginning of the string.
The second loop walks forward until the end of the string, and deals with the fractional part as expected it also uses the distance from the index, but this time accumulates fractional parts:
1/pow(2,<distance-from-decimal-point>)
Worked out example:
1101.11 = 1101 + 0.11
1101 = 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0 = 8 + 4 + 0 + 1 = 13
0.11 = 1/(2^1) + 1/(2^2) = 0.5 + 0.25 = 0.75
1101.11 = 13.75
Beware of malformed input. "10gsh.9701072.67812" will give you a result. It won't mean much :)
This piece of code behaves abnormally: I added some simple print statement
while(q>0)
{
double i;
main=q*10.0;
q=modf(main, &i); //extration of frational part(q) and integer part(i)
cout << "main = " << main << " frac part " << q << " int part " << i << endl;
cin.get();
dec=dec+i*pow(2,-t);
t++;
}
When you input 1101.11, the following output shown:
Enter binary number to convert(e.g: 1101.11 which will be 13.75 in decimal):
1101.11
bin in main 1101.11
p 1101 q 0.11
//inside the above while loop code
main = 1.1 frac part 0.1 int part 1
main = 1 frac part 1 int part 0 //^^^^^Error, given main=1, it should output integer part 1, fraction part 0
main = 10 frac part 1 int part 9 //^^^^^same strange error here, it should exit while already
So you got wrong result. I tested modf separately with input 1, it gave correct result.
So my guess is that you are reading the binary number as double, then tries to convert this double to binary back. There might be something going on under the hood for the precision of number though it shows that it is 1101.11. As suggested by #Useless, You may need to read the number as a string, figure out the substring before and after the decimal point . Then convert this two part into decimal separately.
I need help trying to fix the second part of my program, converting decimal to binary, this is what I have so far and when i compile it i keep getting 0 so im not sure what i did wrong. any help please?
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char string[100];
int s;
char a;
char j;
int sum = 0;
int r;
int q;
printf("B = B to D\n");
printf("D = D to B\n");
printf("choose which one to convert to:");
scanf("%c%c", &a, &j);
if (a == 'B')
{
printf("enter binary number to convert to decimal: ");
scanf("%s", string);
for(s = strlen(string)-1; s >= 0; s--)
{
if(string[s] == '1')
{
sum = sum + pow(2, strlen(string) - (s +1));
}
}
printf("the decimal number is: %d\n", sum);
}
if (a == 'D')
{
printf("enter decimal number to convert to binary: ");
scanf("%s", string);
while (r > 0)
{
r = q%2;
q = q%2;
}
printf("the binary number is: %d\n", r);
}
return 0;
}
There are a few problems here. For one thing, the first time that you check r, it is uninitialized. Another problem is that you're setting both r and q to the same value every time you go through the while loop. You probably want q = q/2 instead of q = q%2. Finally, you're overwriting r every pass through the loop, instead of building up a string of bits. Here's some pseudocode for what you want to do:
output_string = ""
while input > 0:
output_string = concat(input%2, output_string)
input /= 2
print output_string
Note that you're also never converting the string you read in to an integer and putting that in q, so you'll need to do that as well.
This C99 code will do the trick if you want a negative number to be printed as a string of binary digits with a sign:
if (a == 'D')
{
int r;
printf("enter decimal number to convert to binary: ");
scanf("%d", &r);
int i = 0;
int p = (r >= 0) ? (r = -r, 1) : 0;
string[i++] = '\0';
do
{
string[i++] = (r % 2) == 0 ? '0' : '1';
r /= 2;
} while (r != 0);
if (!p)
string[i++] = '-';
int k = 0;
while (--i > k)
{
char t = string[i];
string[i] = string[k];
string[k++] = t;
}
printf("the binary number is: %s\n", string);
}
For example, given -1234 (decimal), the output is -10011010010 (binary). It also handles both the extremes: INT_MAX, -INT_MAX and INT_MIN (assuming 32-bit int):
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: 2147483647
the binary number is: 1111111111111111111111111111111
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: -2147483647
the binary number is: -1111111111111111111111111111111
B = B to D
D = D to B
choose which one to convert to: D
enter decimal number to convert to binary: -2147483648
the binary number is: -10000000000000000000000000000000
If, on the other hand, you want the bit pattern corresponding to the value, then Joachim Pileborg's answer does that for you.
(It's C99 code because it declares variables at convenient points part way through a block, rather than at the start of a block as C89 requires.)
The simplest thing is probably to convert the string input to a proper integer (using e.g. strtol), and the convert that number to a string containing only ones and zeroes.
Something like:
/* Convert a (possibly signed) decimal number in a string to a long integer */
unsigned long number = (unsigned long) strtol(string, NULL, 10);
char output_string[65]; /* If longs are 64 bits, plus one for terminator */
char *output_ptr = output_string;
/* Start with the highest bit, go down to the lowest */
/* sizeof(long) is either 4 or 8 depending on 32 or 64 bit platforms */
/* Multiply with 8 to get the number of bits */
/* -1 because bits are numbered from 0 to 31 (or 63) */
for (int bit = (sizeof(unsigned long) * 8) - 1; bit >= 0; bit--)
{
/* Using right shift to get the current bit into the lowest position */
/* Doing bitwise AND to see if the lowest bit is a one or a zero */
/* Adding '0' makes a a printable ASCII value of a digit */
*output_ptr++ = ((number >> bit) & 1) + '0';
/* `*output_ptr` gets the value that `output_ptr` points to */
/* Then use the `++` operator to increase the pointer */
/* Now `output_ptr` points to the next character in `output_string` */
}
/* Terminate string */
*output_ptr = '\0';
printf("%ld in binary is %s\n", number, output_string);
I have just begun teaching myself C out of K.N King's C Programming: A Modern Approach (2ndEdn).
I'm enjoying it, but am hoping to post the odd question here for advice if appropriate because unfortunately I don't have a tutor and some bits raise more questions then they answer!
I'm doing a question on taking an integer entered and displaying it in octal. It says there is an easy way to do it, but that comes later in the book. I have come up with the following:
// Convert a number to octal
int n, n2, n3, n4, n5, n6;
printf("Enter a number between 0 and 32767: ");
scanf("%d", &n);
n6 = n % 8;
n5 = (n / 8) % 8;
n4 = ((n / 8) / 8) % 8;
n3 = (((n / 8) / 8) / 8) % 8;
n2 = ((((n / 8) / 8) / 8) / 8) % 8;
printf("%d%d%d%d%d", n2, n3, n4, n5, n6);
It works OK, but I'm not good at math and was wondering if there is a more efficient way of doing this or have I done it the only way possible...
If anyone else has the book it's Q4 p.71.
Thanks for your time.
Andrew
P.S I did look in the search engine but couldn't find anything that was doing it this 'slower' way!
Everyone is right in saying that there's a built-in way to do that with printf. But what about doing it yourself?
The first thing that came to mind is that one octal digit is exactly three bits. Therefore you can do the conversion this way:
Loop while n != 0
Isolate the leftmost 3 bits of n into d and print d
Shift n 3 bits to the left
The code is trivial, but I 'm not providing it so you can do it yourself (you will need to be familiar with the bitwise and shift operators in order to do it).
The easy way is probably to use printf()'s %o format specifier:
scanf("%d", &n);
printf("%o", n);
Others have posted the real, production code answer, and now I see from your comments that you haven't done loops yet. Perhaps your book is trying to teach you about recursion:
void print_oct(int n)
{
if (n != 0) {
print_oct(n / 8);
printf("%d", n % 8);
}
}
This works for n > 0.
With loops you can roll up your five very similar lines like this:
for (int d = 8 * 8 * 8 * 8; d > 0; d /= 8)
printf("%d", n / d % 8);
printf("\n");
d will start at 8 * 8 * 8 * 8, which is the divisor you use for n2 and then step through 8 * 8 * 8, 8 * 8, 8 and finally 1, which is the divisor for n6, printing each digit along the way.
A good compiler will actually optimize this by unrolling it back into five lines, so you'll get almost the same thing you started with. The advantage of writing it as a loop is that you can't make a mistake in just one of the lines.
The compiler will also take care of replacing divisions by 8 with shifts by 3 bits. Both give the same result in binary, but the latter is faster.
/* Converts a positive base_10 into base_b */
int DecimalToBase(int n, int b)
{
int rslt=0, digitPos=1;
while (n)
{
rslt += (n%b)*digitPos;
n /= b;
digitPos *= 10;
}
return rslt;
}
Use %o format specifier inside printf
printf("Enter a number between 0 and 32767: ");
scanf("%d", &n);
printf("%o", n);
Since only basics are introduced you don't want (at least at this point) to use functions, loops, bitwise operators, %o format specifier and all that stuff. Here is my basic solution:
int n, d1, d2, d3, d4, d5, o;
printf("Enter a number between 0 and 32767: ");
scanf("%d", &n);
d5 = n % 8;
n /= 8;
d4 = n % 8;
n /= 8;
d3 = n % 8;
n /= 8;
d2 = n % 8;
n /= 8;
d1 = n % 8;
o = 10000 * d1 + 1000 * d2 + 100 * d3 + 10 * d4 + d5;
printf("In octal, your number is: %.5d\n", o);
Note that since n is not needed in output, you can modify (divide) it for every step (thus saving divides, which are computationally and relatively expensive). You are safe up to 32767 (in octal: 77777), as 32768 (8*8*8*8*8 = 8^5 = (2^3)^5 = 2^15) is the first number, that requires six digits in octal: 100000.
This o variable is not really needed, morever it will not work when int is signed 16-bit (on some ancient system), so from this point it's better to just print separate digits.
Existing answers aren't clean enough for my liking. Here's mine:
#include <stdio.h>
#define OCTALBASE 8
#define OCTALSIZE 8
int main(int argc, char **argv) {
int indecimal = 1337;
char output[OCTALSIZE + 1];
output[OCTALSIZE] = '\0';
int outindex = OCTALSIZE;
int outdigit = 0;
int outvalue = indecimal;
while (--outindex >= 0) {
outdigit = outvalue % OCTALBASE;
if (outvalue > 0 || outdigit > 0)
{ output[outindex] = '0' + outdigit; }
else { output[outindex] = ' '; }
outvalue /= OCTALBASE;
}
fprintf(stdout, "{ DEC: %8d, OCT: %s }\n", indecimal, output);
fflush(stdout);
return 0;
}
Result:
{ DEC: 1337, OCT: 2471 }
Convert Decimal to Octal in C Language
#include<stdio.h>
#include<conio.h>
void main()
{
A:
long int n,n1,m=1,rem,ans=0;
clrscr();
printf("\nEnter Your Decimal No :: ");
scanf("%ld",&n);
n1=n;
while(n>0)
{
rem=n%8;
ans=(rem*m)+ans;
n=n/8;
m=m*10;
}
printf("\nYour Decimal No is :: %ld",n1);
printf("\nConvert into Octal No is :: %ld",ans);
printf("\n\nPress 0 to Continue...");
if(getch()=='0')
goto A;
printf("\n\n\n\tThank You");
getch();
}