Binary addition in c, why does run time error occur? - c

i'm trying to write a code which can convert 2 decimal numbers 0 to 1 into binary, then adding them and printing the binary values for the 2 initial numbers AND the final sum. It compiles with no problems however when I run it crashes right after it converts and prints num1 and num2 (the initial numbers), I can't seem to find the problem.
the general formula for binary addition is:
*ith bit of sum = ith bit of binary1 + ith bit of binary2 + carry factor (0 or 1)
if sum > 1, subtract 2 and add 1 to the next operation (which is the carry factor i mentions earlier)
Below is the code
#include <stdio.h>
// Converting decimal number to a binary number
void convertDecToBin(double num, int len, int binary[]) {
// this function STORES conversion result in binary[]
double tmp = num;
binary[0] = 0;
for (int i = 0; i < len; i++) {
tmp *= 2;
binary[i + 1] = tmp >= 1;
if (tmp >= 1) {
tmp -= 1;
}
}
}
// Binary number addition
void addTwoBinary(int binary1[], int binary2[], int sum[]) {
int tmp;
int carry;
for (unsigned int i = 20; i >= 0; i--) {
if (i == 20 || tmp <= 1) {
carry = 0;
}
else if (tmp > 1) {
carry = 1;
}
sum[i] = binary1[i] + binary2[i] + carry;
tmp = sum[i];
if (sum[i] > 1) {
sum[i]-=2;
}
}
}
//Printing the numbers
void PrintBinary(int binary[], int len) {
for (unsigned int i = 0; i < len; i++) {
printf("%d", binary[i]);
}
}
int main(void) {
double num1, num2;
int binary1[30], binary2[30], sum[30];
scanf("%lf", &num1);
scanf("%lf", &num2);
convertDecToBin(num1, 30, binary1);
convertDecToBin(num2, 30, binary2);
printf("num1 is ");
PrintBinary(binary1, 21);
printf("\nnum2 is ");
PrintBinary(binary2, 21);
addTwoBinary(binary1, binary2, sum);
printf("\nsum is ");
PrintBinary(sum, 21);
return 0;
}

Related

*** stack smashing detected ***: terminated

#include <stdio.h>
#include <stdlib.h>
void get_nbits(int num, int n);
void replace_nbits(int num, int n, int val);
void get_nbits_from_pos(int num, int n, int pos);
void replace_nbits_from_pos(int num, int n, int pos, int val);
void toggle_bits_from_pos(int num, int n, int pos);
void print_bits(unsigned int num, int n);
int main()
{
printf("\tThis program is to show the below mentioned bitwise functions\n\n");
printf("Select bit operation from below list:\n1. get_nbits\n2. set_nbits\n3. get_nbits_from_pos\n");
printf("4. set_nbits_from_pos\n5. toggle_bits_from_pos\n6. print_bits\n");
printf("Enter your choice: ");
int choice,num,n,pos,val;
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
get_nbits(num,n);
printf("\n");
break;
case 2:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter val: ");
scanf("%d",&val);
replace_nbits(num,n,val);
printf("\n");
break;
case 3:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter pos: ");
scanf("%d",&pos);
get_nbits_from_pos(num,n,pos);
printf("\n");
break;
case 4:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter val: ");
scanf("%d",&val);
printf("Enter pos: ");
scanf("%d",&pos);
replace_nbits_from_pos(num,n,pos,val);
printf("\n");
break;
case 5:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
printf("Enter pos: ");
scanf("%d",&pos);
toggle_bits_from_pos(num,n,pos);
printf("\n");
break;
case 6:
printf("Enter number: ");
scanf("%d",&num);
printf("Enter n: ");
scanf("%d",&n);
print_bits(num,n);
printf("\n");
break;
}
}
void get_nbits(int num, int n)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt++;
}
for(int i=0;i<8;i++)
{
bin_num[i+cnt] = 0;
}
printf("The binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
for(int i=0;i<n;i++)
{
bin_dig = bin_dig + multiple*bin_num[i];
multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num + rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void replace_nbits(int num, int n, int val)
{
int bin_num1[9],bin_num2[9];
int cnt1 = 0,cnt2 = 0;
int bin_dig = 0,bin_dig2 = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num1[cnt1] = num % 2;
num = num / 2;
cnt1++;
}
for(int i=0;i<8;i++)
{
bin_num1[i+cnt1] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
while (val > 0) {
bin_num2[cnt2] = val % 2;
val = val / 2;
cnt2++;
}
for(int i=0;i<8;i++)
{
bin_num2[i+cnt2] = 0;
}
printf("\nThe binary form of given value: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num2[i]);
}
for(int i=0;i<n;i++)
{
bin_dig = bin_dig + multiple*bin_num2[i];
multiple*=10;
}
multiple = 1;
int temp = bin_dig;
for(int i=0;i<n;i++)
{
bin_num1[i] = temp%10;
temp/=10;
}
printf("\nThe binary form of given number after replacing is: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
for(int i=0;i<cnt1;i++)
{
bin_dig2 = bin_dig2 + multiple*bin_num1[i];
multiple*=10;
}
while ( bin_dig2 > 0)
{
rem = bin_dig2 % 10;
decimal_num = decimal_num + rem * base;
bin_dig2 = bin_dig2 / 10;
base = base * 2;
}
printf("\nThe decimal from given number after replacing is: %d\n",decimal_num);
}
void get_nbits_from_pos(int num, int n, int pos)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt++;
}
for(int i=0;i<8;i++)
{
bin_num[i+cnt] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
int from_num = 0;
for(int i = pos;from_num<n;i--,from_num++)
{
bin_dig = bin_dig + multiple*bin_num[i];
if(bin_dig==1) multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num + rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void replace_nbits_from_pos(int num, int n, int pos, int val)
{
int bin_num1[9],bin_num2[9];
int cnt1 = 0,cnt2 = 0;
int bin_dig = 0,bin_dig2 = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num1[cnt1] = num % 2;
num = num / 2;
cnt1++;
}
for(int i=0;i<8;i++)
{
bin_num1[i+cnt1] = 0;
}
printf("\nThe binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
while (val > 0) {
bin_num2[cnt2] = val % 2;
val = val / 2;
cnt2++;
}
for(int i=0;i<8;i++)
{
bin_num2[i+cnt2] = 0;
}
printf("\nThe binary form of given value: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num2[i]);
}
for(int i=n;i>0;i--)
{
bin_dig = bin_dig + multiple*bin_num2[i];
if(bin_dig==1) multiple*=10;
}
multiple = 1;
int temp = bin_dig;
printf("\n%d",bin_dig);
for(int i=pos;i>(pos-n);i--)
{
bin_num1[i] = temp%10;
temp/=10;
}
printf("\nThe binary form of given number after replacing is: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num1[i]);
}
for(int i=0;i<8;i++)
{
bin_dig2 = bin_dig2 + multiple*bin_num1[i];
multiple*=10;
}
while ( bin_dig2 > 0)
{
rem = bin_dig2 % 10;
decimal_num = decimal_num + rem * base;
bin_dig2 = bin_dig2 / 10;
base = base * 2;
}
printf("\nThe decimal from given number after replacing is: %d\n",decimal_num);
}
void toggle_bits_from_pos(int num, int n, int pos)
{
int bin_num[9];
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt++;
}
for(int i=0;i<8;i++)
{
bin_num[i+cnt] = 0;
}
printf("The binary form of given number: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
int from_num = 0;
for(int i = pos;from_num<n;i--,from_num++)
{
bin_num[i] = bin_num[i]^1;
}
printf("\nThe binary form of given number after toggling: ");
for(int i=7;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
for(int i=0;i<8;i++)
{
bin_dig = bin_dig + multiple*bin_num[i];
multiple*=10;
}
while ( bin_dig > 0)
{
rem = bin_dig % 10;
decimal_num = decimal_num + rem * base;
bin_dig = bin_dig / 10;
base = base * 2;
}
printf("\nThe decimal number is: %d\n",decimal_num);
}
void print_bits(unsigned int num, int n)
{
int* bin_num = malloc(n*sizeof(int));
int cnt = 0;
int bin_dig = 0;
int multiple = 1;
int decimal_num = 0, base = 1, rem;
while (num > 0) {
bin_num[cnt] = num % 2;
num = num / 2;
cnt++;
}
if(n>num)
{
for(int i=0;i<n;i++)
{
bin_num[i+cnt] = 0;
}
}
if(cnt>n)
{
printf("The n value is lower than the orignal number of digits\n");
n = cnt;
}
printf("The binary form of given number: ");
for(int i=n-1;i>=0;i--)
{
printf("%d ",bin_num[i]);
}
free(bin_num);
}
I'm a beginner and working with Arrays switch cases and loops of arrays concept coding to do some operations on binary numbers using arrays Here I am able to get the output as expected, but I can't figure out the problem of *** stack smashing detected ***: terminated. This comes at the end of the output I don't know why; anyone can help me with it please? And please tell me what the error means.
This answer is not related for the error, however, using this bit position arithmetic technique you would get rid of the main causes of that error. In this technique you don't have to use neither arrays nor number base conversions but bit arithmetics only.
Consider the number 105 which would be expressed as 01101001 in 8-bit binary right? If it is assigned to an int there will be 24 more digits toward MSb (Most Significant bit). Using bit position arithmetic we can read and print the bit values and we can slice between any 2 positions within the type's bit count range.
Here I show how it could be done using your 2 functions called get_nbits and get_nbits_from_msb_pos (I changed the 2nd one's name to specify the direction operation). I modified their content for this purpose and also added a utility function called printBinary to print binary values of a given int variable, within the desired range.
#include <stdio.h>
#define mBitCount(var) (sizeof(var) * 8)
void printBinary(int val, int from, int to);
void get_nbits(int num, int n);
void replace_nbits(int num, int n, int val);
void get_nbits_from_msb_pos(int num, int n, int pos);
void replace_nbits_from_msb_pos(int num, int n, int pos, int val);
void toggle_nbits_from_msb_pos(int num, int n, int pos);
int main(void) {
/* 105 in decimal, 01101001 in 8-bit binary */
#define NUM 105
get_nbits(NUM, 4);
get_nbits_from_msb_pos(NUM, 4, 6);
replace_nbits(NUM, 4, 7);
replace_nbits_from_msb_pos(NUM, 4, 6, 15);
toggle_nbits_from_msb_pos(NUM, 4, 6);
return 0;
}
void printBinary(int val, int from, int to) {
int bit_count = mBitCount(val);
if(from < to) {
puts("Argument error: from cannot be lesser than or equal to 'to'");
return;
}
else if(from >= bit_count || to < 0) {
puts("Argument error: Position values out of range");
return;
}
for(int i = from; i >= to; i--)
{
if((val & (1 << i))) {
// The ith digit is one
printf("%d",1);
}
else {
// The ith digit is zero
printf("%d",0);
}
}
putchar('\n');
}
void get_nbits(int num, int n)
{
puts("\nget_nbits:");
printf("Parameters: num %d, n %d\n", num, n);
if(n >= mBitCount(num)) {
printf("Argument error: The n must not exceed the bit count of num type which is: %lu\n", (sizeof(num) * 8));
return;
}
puts("The binary form of given number: ");
printBinary(num, mBitCount(num) - 1, 0);
// No need to align since bits ranges to 0th bit
int decimal_num = num & ((1 << n) - 1);
printf("The decimal number is: %d\n",decimal_num);
}
void replace_nbits(int num, int n, int val)
{
puts("\nreplace_nbits:");
printf("Parameters: num %d, n %d, val %d\n", num, n, val);
if(n >= mBitCount(num)) {
printf("Argument error: The n must not exceed the bit count of num type which is: %lu\n", (sizeof(num) * 8));
return;
}
puts("The binary form of given number: ");
printBinary(num, mBitCount(num) - 1, 0);
puts("The binary form of given value: ");
printBinary(val, n - 1, 0);
// No need to align since bits ranges to 0th bit
int mask = (1 << n) - 1; // Set n bits from zero to 1
int decimal_num = num & ~mask; // Clear out the bits that will be replaced
decimal_num |= val & mask;
puts("The binary form of given number after replacing is: ");
printBinary(decimal_num, mBitCount(num) - 1, 0);
printf("The decimal number is: %d\n",decimal_num);
}
// Get n bits from Most Significant Bit (from left to right)
void get_nbits_from_msb_pos(int num, int n, int pos)
{
puts("\nget_nbits_from_msb_pos:");
printf("Parameters: num %d, n %d, pos %d\n", num, n, pos);
if((pos - n) < 0) {
puts("Argument error: n from position should not underflow the bit position");
return;
}
int decimal_num = 0;
puts("The binary form of given number: ");
printBinary(num, mBitCount(num) - 1, 0);
int mask = ((1 << (pos + 1)) - 1); // Mask beyond the pos toward MSb
mask &= ~((1 << ((pos + 1) - n)) - 1); // Mask below pos - n toward LSb
// Slice the num between the pos and n, and then align it to the right
// in order to get the correct value
decimal_num = ((num & mask) >> (pos - (n - 1)));
printf("The decimal number is: %d\n",decimal_num);
}
// Replace n bits from Most Significant Bit (from left to right)
void replace_nbits_from_msb_pos(int num, int n, int pos, int val)
{
puts("\nreplace_nbits_from_msb_pos:");
printf("Parameters: num %d, n %d, pos %d, val %d\n", num, n, pos, val);
if((pos - n) < 0) {
puts("Argument error: n from position should not underflow the bit position");
return;
}
int decimal_num = 0;
puts("The binary form of given number: ");
printBinary(num, mBitCount(num) - 1, 0);
puts("The binary form of given value: ");
printBinary(val, n - 1, 0);
int mask = ((1 << (pos + 1)) - 1); // Mask beyond the pos toward MSb
mask &= ~((1 << ((pos + 1) - n)) - 1); // Mask below pos - n toward LSb
decimal_num = num & ~mask; // Clear the corresponding bits first
decimal_num |= val << (pos - (n - 1)); // Replace the corresponding bits
puts("The binary form of given number after replacing is: ");
printBinary(decimal_num, mBitCount(num) - 1, 0);
printf("The decimal number is: %d\n",decimal_num);
}
void toggle_nbits_from_msb_pos(int num, int n, int pos)
{
puts("\ntoggle_nbits_from_msb_pos:");
printf("Parameters: num %d, n %d, pos %d\n", num, n, pos);
if((pos - n) < 0) {
puts("Argument error: n from position should not underflow the bit position");
return;
}
puts("The binary form of given number: ");
printBinary(num, mBitCount(num) - 1, 0);
int decimal_num = num, i = pos - n; // Get the start index
// Start toggling from start index to the pos
do {
decimal_num ^= 1 << i;
i++;
}
while(i <= pos);
puts("The binary form of given number after toggling: ");
printBinary(decimal_num, mBitCount(decimal_num) - 1, 0);
printf("The decimal number is: %d\n",decimal_num);
}
The output
get_nbits:
Parameters: num 105, n 4
The binary form of given number:
00000000000000000000000001101001
The decimal number is: 9
get_nbits_from_msb_pos:
Parameters: num 105, n 4, pos 6
The binary form of given number:
00000000000000000000000001101001
The decimal number is: 13
replace_nbits:
Parameters: num 105, n 4, val 7
The binary form of given number:
00000000000000000000000001101001
The binary form of given value:
0111
The binary form of given number after replacing is:
00000000000000000000000001100111
The decimal number is: 103
replace_nbits_from_msb_pos:
Parameters: num 105, n 4, pos 6, val 15
The binary form of given number:
00000000000000000000000001101001
The binary form of given value:
1111
The binary form of given number after replacing is:
00000000000000000000000001111001
The decimal number is: 121
toggle_nbits_from_msb_pos:
Parameters: num 105, n 4, pos 6
The binary form of given number:
00000000000000000000000001101001
The binary form of given number after toggling:
00000000000000000000000000010101
The decimal number is: 21
stack smashing occur when one exceeds the size of a specific array(buffer overflow). It a defense mechanism to prevent overwriting of data. Please check your for loop in your functions the value of cnt goes beyond 9 which the size of the array. You can also you refer to What is the "stack smashing detected" error?

I want to print a series of Armstrong numbers which lie between m and n. Here m and n are the two inputs given by the user

I am trying to print the series but whenever I set the range (input given by me) above 407. I only get the output till 407. However, when I set the range below 407 it gives me the result according to the input I have given. Can anybody tell me what I'm doing wrong?
I used an online compiler (www.onlinegdb.com) to write my code.
Here is the code.
#include<stdio.h>
#include<stdlib.h>
int
main ()
{
int m, n;
printf
("Enter two numbers to find the Armstrong numbers that lie between them.\n");
scanf ("%d%d", &m, &n);
system("clear");
if(m>n)
{
m = m + n;
n = m - n;
m = m - n;
}
for (; m < n; m++)
{
int i = m + 1, r, s = 0, t;
t = i;
while (i > 0)
{
r = i % 10;
s = s + (r * r * r);
i = i / 10;
}
if (t == s)
printf ("%d ", t);
}
return 0;
}
enter image description here
enter image description here
Try this code!!!
#include <math.h>
#include <stdio.h>
int main() {
int low, high, number, originalNumber, rem, count = 0;
double result = 0.0;
printf("Enter two numbers(intervals): ");
scanf("%d %d", &low, &high);
printf("Armstrong numbers between %d and %d are: ", low, high);
// swap numbers if high < low
if (high < low) {
high += low;
low = high - low;
high -= low;
}
// iterate number from (low + 1) to (high - 1)
// In each iteration, check if number is Armstrong
for (number = low + 1; number < high; ++number) {
originalNumber = number;
// number of digits calculation
while (originalNumber != 0) {
originalNumber /= 10;
++count;
}
originalNumber = number;
// result contains sum of nth power of individual digits
while (originalNumber != 0) {
rem = originalNumber % 10;
result += pow(rem, count);
originalNumber /= 10;
}
// check if number is equal to the sum of nth power of individual digits
if ((int)result == number) {
printf("%d ", number);
}
// resetting the values
count = 0;
result = 0;
}
return 0;
}
Try this code :
#include <stdio.h>
#include <math.h>
int main()
{
int start, end, i, temp1, temp2, remainder, n = 0, result = 0;
printf(“Enter start value and end value : “);
scanf(“%d %d”, &start, &end);
printf(“\nArmstrong numbers between %d an %d are: “, start, end);
for(i = start + 1; i < end; ++i)
{
temp2 = i;
temp1 = i;
while (temp1 != 0)
{
temp1 /= 10;
++n;
}
while (temp2 != 0)
{
remainder = temp2 % 10;
result += pow(remainder, n);
temp2 /= 10;
}
if (result == i) {
printf(“%d “, i);
}
n = 0;
result = 0;
}
printf(“\n”);
return 0;
}

Trying to compute Armstrong numbers in C: program prints 000..... and hangs

I wrote a C program to find all Armstrong numbers in a user-defined range. There was no compilation error and no logical errors, but upon running program produced by the Turbo C compiler, it somehow prints 000000.... and hangs. Below is the code that was written.
#include <conio.h>
#include <stdio.h>
void main() {
int n1, n2, sum, n_s;
printf("Enter the lower limit: ");
scanf("%d", &n1);
fflush(stdin);
printf("\nEnter the upper limit: ");
scanf("%d", &n2);
while (n1 <= n2) {
n_s = n1;
sum = 0;
while (n1 != 0) {
n1 = n1 % 10;
sum += n1 * n1 * n1;
n1 = n1 / 10;
}
if (sum == n_s) {
printf("%d", n_s);
}
n1++;
}
getch();
}
I don't know where I could have possibly gone wrong.
You need to add two temporary variables.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1, n2, sum, tmp, digit;
printf("Enter the lower limit: ");
scanf("%d", &n1);
printf("\nEnter the upper limit: ");
scanf("%d", &n2);
while (n1 <= n2) {
sum = 0;
tmp = n1;
while (tmp != 0) {
digit = tmp % 10;
sum += digit * digit * digit;
tmp = tmp / 10;
}
if (sum == n1) {
printf("%d\n", n1);
}
n1++;
}
exit(EXIT_SUCCESS);
}
Problem: does not calculate all Armstrong numbers (obligatory OEIS link) only the three digit ones. To compute all n-narcissistic numbers you need to know the number of decimal digits and compute the power accordingly. As a short sketch:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// ALL CHECKS OMMITTED!
int decimal_digits(int number)
{
// actually wrong, but we don't use negative numbers here
// and can safely set log(0) = 1
if (number <= 0) {
return 1;
}
return (int) (floor(log10(number)) + 1);
}
int main()
{
int n1, n2, sum, tmp, digit, dec_digits;
printf("Enter the lower limit: ");
scanf("%d", &n1);
printf("\nEnter the upper limit: ");
scanf("%d", &n2);
while (n1 <= n2) {
sum = 0;
dec_digits = decimal_digits(n1);
tmp = n1;
while (tmp != 0) {
digit = tmp % 10;
sum += (int) (floor(pow((double) digit, (double) dec_digits)));
tmp = tmp / 10;
}
if (sum == n1) {
printf("%d\n", n1);
}
n1++;
}
exit(EXIT_SUCCESS);
}
But that is really only a sketch! A lot of ugly casting and even more assumptions about the environment etc.!
Finds the Armstrong numbers up to 1741725 quite quickly but needs a couple of minutes for the rest (still at 146511208 after 5 minutes). There is a lot of room for optimization.
EDIT found some time (obligatory XKCD) for two experiments.
The code above needs about 10.5 minutes to find the first 34 Armstrong numbers (low limit = 0, high limit = 912985154). If we get rid of the functions from the math-library and roll our own we can save more than half of that run-time.
#include <stdio.h>
#include <stdlib.h>
// ALL CHECKS OMMITTED!
int decimal_digits(int number);
/*
* If you know for sure that e.g.: sizeof(unsigned long)*CHAR_BITS = 32
* and sizeof(unsigned long long)*CHAR_BITS = 64 you can replace
* the inclusion of stdint.h with the following type definitions
*
* For 32 bit x86:
* typedef unsigned int uint32_t;
* typedef unsigned long long int uint64_t;
*
* For 64 bit x86:
* typedef unsigned int uint32_t;
* typedef unsigned long int uint64_t;
*/
#include <stdint.h>
uint64_t own_pow(uint32_t base, uint32_t exponent);
uint32_t own_ilogb(uint32_t base, uint32_t n);
int decimal_digits(int number)
{
// actually wrong, but we don't use negative numbers here
// and can safely set log(0) = 1
if (number < 10) {
return 1;
}
return (int) (own_ilogb(10,(uint32_t) number) + 1);
}
uint64_t uipow(uint32_t base, uint32_t exponent)
{
uint64_t power = 1;
uint64_t big_base = (uint64_t) base;
while (exponent) {
if (exponent % 2 == 1) {
power *= big_base;
}
exponent >>= 1;
big_base *= big_base;
}
return power;
}
uint32_t own_ilogb(uint32_t base, uint32_t n)
{
uint32_t low = 0, big_low = 1, high = 1, mid, big_mid;
uint64_t big_high = base;
// interval reduction (more useful for big-integers)
while (big_high < n) {
low = high;
big_low = big_high;
high <<= 1;
big_high *= big_high;
}
// the actual bisection
while ((high - low) > 1) {
mid = (low + high) >> 1;
big_mid = big_low * uipow(base, mid - low);
if (n < big_mid) {
high = mid;
big_high = big_mid;
}
if (n > big_mid) {
low = mid;
big_low = big_mid;
}
if (n == big_mid)
return mid;
}
if (big_high == n) {
return high;
}
return low;
}
int main()
{
int n1, n2, sum, tmp, digit, dec_digits;
printf("Enter the lower limit: ");
scanf("%d", &n1);
printf("\nEnter the upper limit: ");
scanf("%d", &n2);
while (n1 <= n2) {
sum = 0;
dec_digits = decimal_digits(n1);
tmp = n1;
while (tmp != 0) {
digit = tmp % 10;
sum += (int) uipow((uint32_t) digit, (uint32_t) dec_digits);
tmp = tmp / 10;
}
if (sum == n1) {
printf("%d\n", n1);
}
n1++;
}
exit(EXIT_SUCCESS);
}
(run in 4 minutes and 7 seconds for the range listed above)
The binary search algorithm for own_ilogb() looks slow, we could exchange that with
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
// vid.: http://stackoverflow.com/questions/7365562/de-bruijn-like-sequence-for-2n-1-how-is-it-constructed for an explanation
static const int tab32[32] = {
0, 9, 1, 10, 13, 21, 2, 29,
11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7,
19, 27, 23, 6, 26, 5, 4, 31
};
static int ilog2(uint32_t value)
{
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return tab32[(uint32_t) (value * 0x07C4ACDD) >> 27];
}
int decimal_digits(int number)
{
double logten2two = 3.3219280948873623478703194294893901759;
// actually wrong, but we don't use negative numbers here
// and can safely set log(0) = 1
if (number < 10) {
return 1;
}
return (int) (ilog2((uint32_t) number) / logten2two + 1.0);
}
This does not save a lot of time--it runs in 3 minutes 38 seconds--but half a minute is not nothing.
Using compiler (GCC 4.8.1) optimization -O3 : 3 minutes 43 seconds
A bit slower (about the same, I just used time and it was not the only process running here)
The outer loop invites to try a parallel approach (here with OpenMP to keep things simple)
int main()
{
int n1, n2, sum, tmp, digit, dec_digits;
int iter;
printf("Enter the lower limit: ");
scanf("%d", &n1);
printf("\nEnter the upper limit: ");
scanf("%d", &n2);
#pragma omp parallel for
for(iter = n1;iter <= n2;iter++) {
sum = 0;
dec_digits = decimal_digits(iter);
tmp = iter;
while (tmp != 0) {
digit = tmp % 10;
sum += (int) uipow((uint32_t) digit, (uint32_t) dec_digits);
tmp = tmp / 10;
}
if (sum == iter) {
printf("%d\n", iter);
}
}
exit(EXIT_SUCCESS);
}
That runs in 2 minutes 15 seconds (user: 8m11.933s because 4 CPUs were working at it in parallel and "user" adds all up), although the output is unsorted, of course.
PS: A lot of C&P involved in this post which might have caused one or the other error here and there. Please inform me about the, in the comments below such that I can repair them.
Here is an improved version of cdlane's code that uses additional
optimizations. It can solve up to 912985153 in 1.2 seconds
(with clang -O3 optimization) on my laptop without parallel
processing.
The extra optimizations are:
updating the string representation incrementally instead of calling sprintf repeatedly
bumping the candidate number when the partial sum becomes too large or too small for the current one.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
unsigned long long next_narcissistic(unsigned long long number, unsigned long long max) {
static size_t power = 0;
static unsigned long long powers[10];
static unsigned long long maxleft[42]; /* enough for 128 bit unsigned long long */
static unsigned long long scale10[42] = { 1 };
char string[64];
size_t length;
while (number < max) {
length = sprintf(string, "%llu", number);
if (length > power) {
for (size_t i = power; i < length; i++) {
scale10[i + 1] = scale10[i] * 10;
}
for (size_t digit = 0; digit < 10; digit++) {
unsigned long long total = 1;
for (size_t j = 0; j < length; j++) {
total *= digit;
}
powers[digit] = total;
}
for (size_t i = 0; i <= length; i++) {
maxleft[i] = (length - i) * powers[9];
}
power = length;
}
unsigned long long sum = 0;
unsigned long long max0 = max < scale10[length] ? max : scale10[length] - 1;
for (size_t i = 0;;) {
sum += powers[string[i++] - '0'];
if (i == length) {
if (sum == number)
return number;
/* bump to next number and update string */
number += 1;
if (number > max0)
break;
for (;;) { /* i is always > 0 because number <= max0 */
i--;
sum -= powers[string[i] - '0'];
if (++string[i] <= '9')
break;
string[i] = '0';
}
continue;
}
if (sum <= number) {
if (sum + maxleft[i] >= number)
continue;
} else {
sum -= powers[string[--i] - '0'];
}
/* bump to next possible number */
number += scale10[length - i] - number % scale10[length - i];
if (number > max0)
break;
for (;;) { /* i is always > 0 because number <= max0 */
i--;
sum -= powers[string[i] - '0'];
if (++string[i] <= '9') {
break;
}
}
for (size_t j = i + 1; j < length; j++) {
string[j] = '0';
}
}
}
return 0;
}
int main(int argc, char *argv[]) {
unsigned long long n1, n2;
if (argc > 1) {
n1 = strtoull(argv[1], NULL, 0);
} else {
printf("Enter the lower limit: ");
scanf("%llu", &n1);
}
if (argc > 2) {
n2 = strtoull(argv[2], NULL, 0);
} else {
printf("Enter the upper limit: ");
scanf("%llu", &n2);
}
for (unsigned long long n = n1; n <= n2; n++) {
n = next_narcissistic(n, n2 + 1);
if (n == 0)
break;
printf("%llu\n", n);
}
return 0;
}
Running an additional 1m50s produces these extra Armstrong numbers upto 1011:
4679307774
32164049650
32164049651
40028394225
42678290603
44708635679
49388550606
82693916578
94204591914
Also it would be theoretically1 possible to reach the largest Armstrong number for base 10, 115132219018763992565095597973971522401 with 128-bit integers, it would still take a very long time.
EDIT Additional optimisations provide for another 100x speed factor and produce these extra Armstrong numbers upto 1018:
28116440335967
4338281769391370
4338281769391371
21897142587612075
35641594208964132
35875699062250035
1Although the last solution fits in 128 bits, the above algorithm would actually fail because it would compute 1040 which barely exceeds the capacity of 128-bit unsigned integers.
A complete rewrite of my previous solution. It can solve to 912985153 in 0.02 seconds (with -O3 optimization) on my system without parallel processing. It can reach the 64 bit limit (4929273885928088826) in just over 9 seconds.
A key optimization is only testing the minimum set of numbers (i.e. shun permutations). And avoid complicated math. The algorithm is modeled on the code in the OEIS definition of this sequence.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MORE_THAN_ENOUGH (128)
unsigned long long sort_digits(unsigned long long number) {
unsigned long long sortedNumber = 0;
for (size_t i = 0; i < 10; i++) {
unsigned long long temporary = number;
while (temporary > 0) {
int digit = temporary % 10;
if (digit == i) {
sortedNumber *= 10;
sortedNumber += digit;
}
temporary /= 10;
}
}
return sortedNumber;
}
int compare(const void *a, const void *b) {
unsigned long long x = *(unsigned long long *) a;
unsigned long long y = *(unsigned long long *) b;
return (x < y) ? -1 : (y < x) ? : 0;
}
unsigned long long power(unsigned long long number, unsigned exponent) {
unsigned long long total = 1;
for (unsigned i = 0; i < exponent; i++) {
total *= number;
}
return total;
}
size_t generate_narcissistic(size_t places, unsigned long long results[]) {
char digits[places];
unsigned long long minimum = power(10, places - 1) - 1;
size_t results_count = 0;
for (size_t i = 0; i < places; i++) {
digits[i] = 0;
}
digits[places - 1] = 1;
bool finished = false;
while (!finished) {
unsigned long long sum = 0, number = 0;
for (size_t i = 0; i < places; i++) {
number *= 10;
number += digits[i];
sum += power(digits[i], places);
}
if (sum > minimum) {
unsigned long long sorted = sort_digits(sum);
if (sorted == number) {
results[results_count++] = sum;
}
}
for (int i = places - 1; i >= 0; i--) {
digits[i] += 1;
if (digits[i] <= 9) {
break;
}
if (i == 0) {
finished = true;
break;
}
for (int j = i - 1; j >= 0; j--) {
if (digits[j] != 9) {
digits[i] = digits[j] + 1;
break;
}
}
}
}
if (results_count != 0) {
qsort(results, results_count, sizeof(unsigned long long), &compare);;
}
return results_count;
}
int main(int argc, char *argv[]) {
unsigned long long n0, n1, n2, narcissistic[MORE_THAN_ENOUGH];
if (argc > 1) {
n1 = strtoull(argv[1], NULL, 0);
} else {
printf("Enter the lower limit: ");
scanf("%llu", &n1);
}
if (argc > 2) {
n2 = strtoull(argv[2], NULL, 0);
} else {
printf("Enter the upper limit: ");
scanf("%llu", &n2);
}
char scratch[MORE_THAN_ENOUGH];
size_t lower_limit = sprintf(scratch, "%llu", n1);
size_t upper_limit = sprintf(scratch, "%llu", n2);
for (size_t places = lower_limit; places <= upper_limit; places++) {
size_t count = generate_narcissistic(places, narcissistic);
for (size_t i = 0; i < count; i++) {
n0 = narcissistic[i];
if (n0 >= n1 && n0 <= n2) {
printf("%llu\n", n0);
}
}
}
return 0;
}
I've tried to be careful in the code such that if you have a unsigned long long of 128 bits, and sufficient patience, you should be able to reach the maximum narcissistic number.
128 BIT UPDATE
I took #chqrlie's advice and made a modified version of the above that uses the gcc/clang 128-bit integers. This allowed the program, after running three and a half days, to reach the 88th and final narcissistic number in base 10. (The emulated 128-bit integers are slower than the hardware 64-bit integers.) Specific changes:
Defined the following and replaced all my unsigned long long declarations with uint128_t:
typedef unsigned __int128 uint128_t;
Grabbed uint128_to_str() and uint128_to_str_iter() from this SO question about how to print uint128_t numbers. Since printf won't handle them directly, these routines convert a uint128_t number to a string that you can print instead. Finally, I simplified the main() routine so I didn't have to deal with any other number conversions -- just simply count up:
uint128_t n0, narcissistic[MORE_THAN_ENOUGH];
for (size_t places = 1; places < 40; places++) {
size_t count = generate_narcissistic(places, narcissistic);
for (size_t i = 0; i < count; i++) {
n0 = narcissistic[i];
printf("%s\n", uint128_to_str(n0));
}
}

convert negative decimal number to binary number

I tried to convert a negative decimal number into a binary number and this code perfectly works on my computer, but the code doesn't work another computer.
I didn't get how it is possible. What is wrong in my code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void decTobin(int dec, int s)
{
int b[s], i = 0;
while (dec >= 0 && i != s - 1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d", dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
}
void ndecTobin(int dec, int s)
{
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
while (dec >= 0 && i != s-1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d",dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
printf("\n");
a[s - 1] = dec;
for (j = s - 2; j >= 0; j--) {
a[j] = b[j];
}
for (j = s - 1; j >= 0; j--) {
if (a[j] == 0)
a[j] = 1;
else
a[j] = 0;
printf("%d",a[j]);
}
for (g = 0; g < s; g++) {
decimalvalue = pow(2, g) * a[g];
decimal += decimalvalue;
}
decimal = decimal + 1;
printf("\n%d\n", decimal);
decTobin(decimal, s);
}
int main()
{
int a, b;
printf("enter a number: ");
scanf(" %d", &a);
printf("enter the base: ");
scanf("%d", &b);
ndecTobin(a, b);
}
decimal and int b[s] not initialized.
By not initializing decimal to 0, it might have the value of 0 on a machine one day and quite different results otherwise.
void decTobin(int dec, int s) {
// while loop does not set all `b`,but following for loop uses all `b`
// int b[s], i = 0;
int b[s] = { 0 }; // or int b[s]; memset(b, 0, sizeof b);
int i = 0;
}
void ndecTobin(int dec, int s) {
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
decimal = 0;
...
decimal += decimalvalue;
}
Minor points:
1) if (b[j] == NULL) b[j] = 0; is strange. NULL is best used as a pointer, yet code is comparing b[j], an int to a pointer. Further, since NULL typically has the arithmetic value of 0, code looks like if (b[j] == 0) b[j] = 0;.
2) decTobin() is challenging to follow. It certainly is only meant for non-negative dec and s. Candidate simplification:
void decTobin(unsigned number, unsigned width) {
int digit[width];
for (unsigned i = width; i-- > 0; ) {
digit[i] = number % 2;
number /= 2;
}
printf("%u ", number); // assume this is for debug
for (unsigned i = 0; i<width; i++) {
printf("%u", digit[i]);
}
}
It looks like you are just printing the number as a binary representation. If so this version would work.
void print_binary(size_t n) {
/* buffer large enough to hold number to print */
unsigned buf[CHAR_BIT * sizeof n] = {0};
unsigned i = 0;
/* handle special case user calls with n = 0 */
if(n == 0) {
puts("0");
return;
}
while(n) {
buf[i++] = n % 2;
n/= 2;
}
/* print buffer backwards for binary representation */
do {
printf("%u", buf[--i]);
} while(i != 0);
}
If you don't like the buffer, you can also do it using recursion like this:
void using_recursion(size_t n)
{
if (n > 1)
using_recursion(n/2);
printf("%u", n % 2);
}
Yet another way is to print evaluating most significant bits first. This however introduces issue of leading zeros which in code below are skipped.
void print_binary2(size_t n) {
/* do not print leading zeros */
int i = (sizeof(n) * 8)-1;
while(i >= 0) {
if((n >> i) & 1)
break;
--i;
}
for(; i >= 0; --i)
printf("%u", (n >> i) & 1);
}
Different OS/processor combinations may result in C compilers that store various kinds of numeric variables in different numbers of bytes. For instance, when I first learned C (Turbo C on a 80368, DOS 5) an int was two bytes, but now, with gcc on 64-bit Linux, my int is apparently four bytes. You need to include some way to account for the actual byte length of the variable type: unary operator sizeof(foo) (where foo is a type, in your case, int) returns an unsigned integer value you can use to ensure you do the right number of bit shifts.

Problems with hex

I get some homework, but i stack in it. Maybe you can help me. Task below.
Read the keyboard integer in the decimal system and establishment of a new system of numbers.
Output in the console number written in the new notation.
I made for 2 to 10 systems only and i can't make from 10 to 36. I tried to make in second loop something like this:
if ( result > 9 ) {
printf("%c", 55+number);
} else {
printf("%d", result);
}
my code:
#include <stdio.h>
int main() {
int number, base;
int i, result;
scanf("%d %d", &number, &base);
if ( number < base ) {
printf("%d\n", number);
} else {
for ( i = base; i <= number / base; i *= base );
for ( int j = i; j >= base; j /= base ) {
result = number / j;
printf("%d", result);
number = number % j;
}
printf("%d\n", number%base);
}
return 0;
}
else condition needs some changes:
1. value to digit conversion needs to apply to the inner loop and to the final printf("%d\n", number % base). Instead of adding in both places, simply make your loop run to j > 0, rather than j >= base and only use the last printf() for \n.
2. Rather than using a magic number 55 use result - 10 + 'A'. It easier to understand and does not depend on ASCII - (does depend on A, B, C ... being consecutive).
3. The rest is OK.
[edit]
#nos pointed out problem with if() condition.
So remove if ( number < base ) { ... else { and change for (i = base; to for (i = 1; making an even more simple solution.
// } else {
for (i = 1; i <= number / base; i *= base)
;
int j;
// for (j = i; j >= base; j /= base) {
for (j = i; j > 0; j /= base) {
result = number / j;
#if 1
if (result > 9) {
// printf("%c", 55 + result);
printf("%c", result - 10 + 'A');
} else {
printf("%d", result);
}
#else
printf("%d", result);
#endif
number = number % j;
}
printf("\n");
// }
int number, base;
scanf("%d %d", &number, &base);
int divisor = base;
while (divisor <= number)
divisor *= base;
while (divisor != 1) {
divisor /= base;
int digit = number / divisor;
number -= digit * divisor;
printf("%c", digit <= 9 ? digit + '0' : digit + 'A' - 10);
}
printf("\n");
return 0;
Caveat: Undefined behavior for numbers greater than ~200000000.
You're on the right track and are very close to the answer. Your program is printing the resulting digits in two places.
I suggest making a single function to output the digits and using it in both places:
void print_digit(int number) {
// your code here
}
You can add characters and integers, so try something more like:
'A' + // some int value
On the other hand, should one like a solution that does not under/overflow, handles all INT_MIN to INT_MAX, no UB, only enter INT_MIN <= number <= INT_MAX, 2 <= base <= 36, and you don't mind recursion.
#include <stdio.h>
#include <stdlib.h>
void print_digit(int x, int base) {
int quot, rem;
quot = x/base;
if (quot) {
print_digit(quot, base);
}
rem = abs(x%base);
if (rem > 9) {
printf("%c", rem - 10 + 'A');
} else {
printf("%d", rem);
}
}
int main() {
int number, base;
scanf("%d %d", &number, &base);
if (number < 0) {
printf("-");
}
print_digit(number, base);
printf("\n");
return 0;
}

Resources