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

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));
}
}

Related

How to print 10 perfect numbers from a user given number in C?

I can't figure out how to print next ten Perfect numbers.
Here's what I have got so far:
#include <stdio.h>
int main() {
int n, c = 1, d = 2, sum = 1;
printf("Enter any number \n");
scanf("%d", &n);
printf("The perfect numbers are:");
while(c <= 10) {
sum = 1;
d = 2;
while(d <= n / 2) { //perfect no
if(n % d == 0) {
sum = sum + d;
}
d++;
}
if(sum == n) {
printf("%d\n", n);
}
c++;
}
return 0;
}
The output I am currently receiving:
input: 2 (say)
output: 6
What I want:
input: 2
output:
6
28
496
8128
33550336
858986905
137438691328
2305843008139952128
2658455991569831744654692615953842176
191561942608236107294793378084303638130997321548169216
I have just started coding. Any help will be appreciated.
The integer overflow issue mentioned by several folks is significant, but secondary. Even if we fix your broken logic, and adjust it to handle larger, fixed sized integers:
#include <stdio.h>
int main() {
unsigned long long number;
printf("Enter any number \n");
scanf("%llu", &number);
printf("The perfect numbers are:\n");
int total = 0;
while (total < 10) {
unsigned long long sum = 1, divisor = 2;
while (divisor <= number / 2) {
if (number % divisor == 0) {
sum += divisor;
}
divisor++;
}
if (sum == number) {
printf("%llu\n", number);
total++;
}
number += 1;
}
return 0;
}
You still wouldn't get past the first four perfect numbers in any reasonable amount of time:
> ./a.out
Enter any number
2
The perfect numbers are:
6
28
496
8128
The primary issue is you're using a bad algorithm. Read about Mersenne primes, and their relationship to perfect numbers, as well as the Lucas-Lehmer test. This approach takes more thought, but surprisingly, not much more code. And will produce more results faster (though eventually bog down as well.)
You have to put the counter after you find a perfect number, so increasing c must happen in the if statement that checks the perfect number, like this:
if(sum==n){
printf("%d",n);
c++;
}
After this you need to increase the number, called n, like this:
n++;
and based on the numbers, #Jonathan Leffler is right, you should use proper variables.
Research, divide and conquer
Perfect numbers are of the form 2p − 1 * (2p − 1).
Code will need extended precision to form 191561942608236107294793378084303638130997321548169216
Increase efficiency
Iterating to <= n / 2 takes far too long. Iterate up to <= n / d
// while(d <= n / 2) {
while(d <= n / d) {
Sample improved code:
bool isprime(unsigned long long x) {
if (x > 3) {
if (x % 2 == 0) {
return false;
}
for (unsigned long t = 3; t <= x / t; t += 2) {
if (x % t == 0) {
return false;
}
}
return true;
}
return x >= 2;
}
Advanced: See Lucas–Lehmer primality test for quick prime test of Mersenne numbers
The below code works for all but the 10th perfect number as code must test for isprime(267 - 1) and I should leave something for OP to do.
static void buff_mul(char *buff, unsigned power_of_2) {
unsigned long long m = 1ull << power_of_2;
size_t len = strlen(buff);
unsigned long long carry = 0;
for (size_t i = len; i > 0;) {
i--;
unsigned long long sum = (buff[i] - '0') * m + carry;
buff[i] = sum % 10 + '0';
carry = sum / 10;
}
while (carry) {
memmove(buff + 1, buff, ++len);
buff[0] = carry % 10 + '0';
carry /= 10;
}
}
void print_perfext(unsigned p) {
// 2**(p-1) * (2**p - 1)
assert(p > 1 && p <= 164);
char buff[200] = "1";
buff_mul(buff, p);
buff[strlen(buff) - 1]--; // Decrement, take advantage that the LSDigit is never 0
buff_mul(buff, p - 1);
puts(buff);
fflush(stdout);
}
//unsigned next_prime(unsigned first_numeber_to_test_if_prime) {
#include <stdio.h>
int main() {
unsigned p = 0;
for (unsigned i = 0; i < 9; i++) {
// If p prime && 2**p − 1 is prime, then 2**(p − 1) * (2**p − 1) is a perfect number.
while (!isprime(p) || !isprime((1uLL << p) - 1))
p++;
printf("%2u ", p);
print_perfext(p);
p++;
}
return 0;
}
Output
2 6
3 28
5 496
7 8128
13 33550336
17 8589869056
19 137438691328
31 2305843008139952128
61 2658455991569831744654692615953842176
From output you wrote I belive that u want to show 10 first perfect numbers
Now u are only showing 6 because u show them from 1 to 10. In this range there is only 6.
I wrote sth like this:
#include <stdio.h>
int isperfect(int input) {
int sum = 0, value = input / 2;
do {
if (input % value == 0) sum += value;
value--;
} while (value);
if (input == sum) return 1;
else return 0;
}
int main() {
int i;
int count;
for (i = 2, count = 0; count < 4; i++) {
if (isperfect(i) == 1) {
count++;
printf("%d\n", i);
}
}
return 0;
}
But I don't recomend counting more than 4 because its gonna take too much time

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

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;
}

Run-time error occurs when input value is greater than 100000

I am trying to implement the sieve of eratosthenes in C. The code works for small input values, but once the input goes beyond a certain range, a run- time error is thrown. This is the second problem in the classical section of the SPOJ base. What is the mistake?
#include<stdio.h>
#include<math.h>
int prime(unsigned long int, unsigned long int);
int main()
{
int nitem;
unsigned long int sn,fn;
scanf("%d", &nitem);
while(nitem)
{
scanf("%lu", &fn);
//printf("%d",fn);
scanf("%lu", &sn);
prime(fn, sn);
nitem--;
}
return 0;
}
int prime(unsigned long int fn, unsigned long int sn)
{
unsigned long int prim[100000];
int i,j,k;
for(i = 0; i < 100000; i++)
{
prim[i] = 1;
}
prim[0] = 0;
prim[1] = 0;
//printf("%d", sn);
//printf("%d", k);
//printf("%d", (k <= sn));
for(k = 2; k <= sqrt(sn); k++)
{
// printf("alksnc%5d", k);
if(prim[k] == 1)
{
for(j = 2; (k * j) <= sn; j++)
{
//printf("%d", prim[k]);
prim[k * j] = 0;
}
}
}
for(int i = 0; i <= sn; i++)
{
if(prim[i] !=0 && i >= fn)
{
printf("%lu\n", i);
}
}
printf("\n");
return;
}
Input:
1
100000 100345
output:
run time error
Input:
1
3 5
output:
3
5
We can make more efficient use of memory (2x) by only sieving odd numbers as all the even numbers you're processing waste time and space. It's trickier to work out but gives us something like:
#include <math.h>
#include <libc.h>
#define MAX_ODD_PRIMES 1048576
void prime(unsigned long fn, unsigned long sn)
{
unsigned char primes[MAX_ODD_PRIMES];
for (unsigned long i = 0; i < MAX_ODD_PRIMES; i++)
{
primes[i] = TRUE;
}
primes[0] = 0; // preset first odd, '1'
for (unsigned long k = 3; k <= sqrt(sn) + 1; k += 2)
{
if (primes[k / 2])
{
for (unsigned long j = 3; (k * j) <= sn; j += 2)
{
primes[k * j / 2] = FALSE;
}
}
}
if (fn <= 2)
{
printf("2\n");
fn = 3;
}
for (unsigned long i = fn / 2; i * 2 + 1 <= sn; i++)
{
if (primes[i])
{
printf("%lu\n", i * 2 + 1);
}
}
}
EXAMPLE
> ./a.out
1 1999900 2000000
1999957
1999969
1999979
1999993
>
1) Array range error.
By changing code
for (j = 2; (k * j) <= sn; j++) {
if (k * j >= 100000) {
printf("Out of range %d %d\n", k, j);
exit(1);
}
prim[k * j] = 0;
}
}
With input 2, 100000
Output
Out of range 2 50000
By using an array (VLA) sized to the task, this is avoided. Many other optimizations available. Consider also a malloc() array.
void prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[sn + 1];
2) int prime() eventually performs return; where return something; is expected. Suggest changing function to void prime()
int prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[100000];
...
printf("\n");
return;
}

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.

Finding the length of an integer in C

I would like to know how I can find the length of an integer in C.
For instance:
1 => 1
25 => 2
12512 => 5
0 => 1
and so on.
How can I do this in C?
C:
You could take the base-10 log of the absolute value of the number, round it down, and add one. This works for positive and negative numbers that aren't 0, and avoids having to use any string conversion functions.
The log10, abs, and floor functions are provided by math.h. For example:
int nDigits = floor(log10(abs(the_integer))) + 1;
You should wrap this in a clause ensuring that the_integer != 0, since log10(0) returns -HUGE_VAL according to man 3 log.
Additionally, you may want to add one to the final result if the input is negative, if you're interested in the length of the number including its negative sign.
Java:
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
N.B. The floating-point nature of the calculations involved in this method may cause it to be slower than a more direct approach. See the comments for Kangkan's answer for some discussion of efficiency.
If you're interested in a fast and very simple solution, the following might be quickest (this depends on the probability distribution of the numbers in question):
int lenHelper(unsigned x) {
if (x >= 1000000000) return 10;
if (x >= 100000000) return 9;
if (x >= 10000000) return 8;
if (x >= 1000000) return 7;
if (x >= 100000) return 6;
if (x >= 10000) return 5;
if (x >= 1000) return 4;
if (x >= 100) return 3;
if (x >= 10) return 2;
return 1;
}
int printLen(int x) {
return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}
While it might not win prizes for the most ingenious solution, it's trivial to understand and also trivial to execute - so it's fast.
On a Q6600 using MSC I benchmarked this with the following loop:
int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);
This solution takes 0.062s, the second-fastest solution by Pete Kirkham using a smart-logarithm approach takes 0.115s - almost twice as long. However, for numbers around 10000 and below, the smart-log is faster.
At the expense of some clarity, you can more reliably beat smart-log (at least, on a Q6600):
int lenHelper(unsigned x) {
// this is either a fun exercise in optimization
// or it's extremely premature optimization.
if(x >= 100000) {
if(x >= 10000000) {
if(x >= 1000000000) return 10;
if(x >= 100000000) return 9;
return 8;
}
if(x >= 1000000) return 7;
return 6;
} else {
if(x >= 1000) {
if(x >= 10000) return 5;
return 4;
} else {
if(x >= 100) return 3;
if(x >= 10) return 2;
return 1;
}
}
}
This solution is still 0.062s on large numbers, and degrades to around 0.09s for smaller numbers - faster in both cases than the smart-log approach. (gcc makes faster code; 0.052 for this solution and 0.09s for the smart-log approach).
int get_int_len (int value){
int l=1;
while(value>9){ l++; value/=10; }
return l;
}
and second one will work for negative numbers too:
int get_int_len_with_negative_too (int value){
int l=!value;
while(value){ l++; value/=10; }
return l;
}
You can write a function like this:
unsigned numDigits(const unsigned n) {
if (n < 10) return 1;
return 1 + numDigits(n / 10);
}
length of n:
length = ( i==0 ) ? 1 : (int)log10(n)+1;
The number of digits of an integer x is equal to 1 + log10(x). So you can do this:
#include <math.h>
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
printf("x has %d digits\n", 1 + (int)log10(x));
}
Or you can run a loop to count the digits yourself: do integer division by 10 until the number is 0:
int numDigits = 0;
do
{
++numDigits;
x = x / 10;
} while ( x );
You have to be a bit careful to return 1 if the integer is 0 in the first solution and you might also want to treat negative integers (work with -x if x < 0).
A correct snprintf implementation:
int count = snprintf(NULL, 0, "%i", x);
The most efficient way could possibly be to use a fast logarithm based approach, similar to those used to determine the highest bit set in an integer.
size_t printed_length ( int32_t x )
{
size_t count = x < 0 ? 2 : 1;
if ( x < 0 ) x = -x;
if ( x >= 100000000 ) {
count += 8;
x /= 100000000;
}
if ( x >= 10000 ) {
count += 4;
x /= 10000;
}
if ( x >= 100 ) {
count += 2;
x /= 100;
}
if ( x >= 10 )
++count;
return count;
}
This (possibly premature) optimisation takes 0.65s for 20 million calls on my netbook; iterative division like zed_0xff has takes 1.6s, recursive division like Kangkan takes 1.8s, and using floating point functions (Jordan Lewis' code) takes a whopping 6.6s. Using snprintf takes 11.5s, but will give you the size that snprintf requires for any format, not just integers. Jordan reports that the ordering of the timings are not maintained on his processor, which does floating point faster than mine.
The easiest is probably to ask snprintf for the printed length:
#include <stdio.h>
size_t printed_length ( int x )
{
return snprintf ( NULL, 0, "%d", x );
}
int main ()
{
int x[] = { 1, 25, 12512, 0, -15 };
for ( int i = 0; i < sizeof ( x ) / sizeof ( x[0] ); ++i )
printf ( "%d -> %d\n", x[i], printed_length ( x[i] ) );
return 0;
}
Yes, using sprintf.
int num;
scanf("%d",&num);
char testing[100];
sprintf(testing,"%d",num);
int length = strlen(testing);
Alternatively, you can do this mathematically using the log10 function.
int num;
scanf("%d",&num);
int length;
if (num == 0) {
length = 1;
} else {
length = log10(fabs(num)) + 1;
if (num < 0) length++;
}
int digits=1;
while (x>=10){
x/=10;
digits++;
}
return digits;
sprintf(s, "%d", n);
length_of_int = strlen(s);
You may use this -
(data_type)log10(variable_name)+1
ex:
len = (int)log10(number)+1;
In this problem , i've used some arithmetic solution . Thanks :)
int main(void)
{
int n, x = 10, i = 1;
scanf("%d", &n);
while(n / x > 0)
{
x*=10;
i++;
}
printf("the number contains %d digits\n", i);
return 0;
}
Quite simple
int main() {
int num = 123;
char buf[50];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", strlen (buf));
return 0;
}
keep dividing by ten until you get zero, then just output the number of divisions.
int intLen(int x)
{
if(!x) return 1;
int i;
for(i=0; x!=0; ++i)
{
x /= 10;
}
return i;
}
This goes for both negative and positive intigers
int get_len(int n)
{
if(n == 0)
return 1;
if(n < 0)
{
n = n * (-1); // if negative
}
return log10(n) + 1;
}
Same logic goes for loop
int get_len(int n)
{
if(n == 0)
return 1;
int len = 0;
if(n < 0)
n = n * (-1);
while(n > 1)
{
n /= 10;
len++;
}
return len;
}
Why don't you cast your integer to String and get length like this :
int data = 123;
int data_len = String(data).length();
For simple programs...
int num = 456, length=0 // or read value from the user to num
while(num>0){
num=num/10;
length++;
}
Use another variable to retain the initial num value.
In my opinion the shortest and easiest solution would be:
int length , n;
printf("Enter a number: ");
scanf("%d", &n);
length = 0;
while (n > 0) {
n = n / 10;
length++;
}
printf("Length of the number: %d", length);
My way:
Divide as long as number is no more divisible by 10:
u8 NumberOfDigits(u32 number)
{
u8 i = 1;
while (number /= 10) i++;
return i;
}
I don't know how fast is it in compared with other propositions..
int intlen(int integer){
int a;
for(a = 1; integer /= 10; a++);
return a;
}
A more verbose way would be to use this function.
int length(int n)
{
bool stop;
int nDigits = 0;
int dividend = 1;
do
{
stop = false;
if (n > dividend)
{
nDigits = nDigits + 1;
dividend = dividend * 10;
}
else {
stop = true;
}
}
while (stop == false);
return nDigits;
}
int returnIntLength(int value){
int counter = 0;
if(value < 0)
{
counter++;
value = -value;
}
else if(value == 0)
return 1;
while(value > 0){
value /= 10;
counter++;
}
return counter;
}
I think this method is well suited for this task:
value and answers:
-50 -> 3 //it will count - as one character as well if you dont want to count
minus then remove counter++ from 5th line.
566666 -> 6
0 -> 1
505 -> 3
Solution
Use the limit where the integer length changes, in the case of the decimal it is a power of 10, and thus use a counter for each verification that the specified integer has not exceeded the limit.
With the math.h dependency:
#include <math.h>
int count_digits_of_integer(unsigned int integer) {
int count = 1;
while(1) {
int limit = pow(10, count);
if(integer < limit) break;
count++;
}
return count;
}
Without dependency:
int int_pow(int base, int exponent) {
int potency = base;
for(int i = 1; i < exponent; i++) potency *= base;
return potency;
}
int count_digits_of_integer(unsigned int integer) {
int count = 1;
while(1) {
int limit = int_pow(10, count);
if(integer < limit) break;
count++;
}
return count;
}
Implementation
#include <stdio.h>
// Copy and paste the solution code here
int main() {
printf("%i -> (%i digits)\n", 0, count_digits_of_integer(0));
printf("%i -> (%i digits)\n", 12, count_digits_of_integer(12));
printf("%i -> (%i digits)\n", 34569, count_digits_of_integer(34569));
printf("%i -> (%i digits)\n", 1234, count_digits_of_integer(1234));
printf("%i -> (%i digits)\n", 3980000, count_digits_of_integer(3980000));
printf("%i -> (%i digits)\n", 100, count_digits_of_integer(100));
printf("%i -> (%i digits)\n", 9, count_digits_of_integer(9));
printf("%i -> (%i digits)\n", 385784, count_digits_of_integer(385784));
return 0;
}
Output:
0 -> (1 digits)
12 -> (2 digits)
34569 -> (5 digits)
1234 -> (4 digits)
3980000 -> (7 digits)
100 -> (3 digits)
9 -> (1 digits)
385784 -> (6 digits)
Hmm, maybe like this...?
#define _LEN(x) (sizeof(#x)/sizeof(char)-1)
You can also use this function to find the length of an integer:
int countlength(int number)
{
static int count = 0;
if (number > 0)
{
count++;
number /= 10;
countlength(number);
}
return count;
}
I think I got the most efficient way to find the length of an integer
its a very simple and elegant way
here it is:
int PEMath::LengthOfNum(int Num)
{
int count = 1; //count starts at one because its the minumum amount of digits posible
if (Num < 0)
{
Num *= (-1);
}
for(int i = 10; i <= Num; i*=10)
{
count++;
}
return count;
// this loop will loop until the number "i" is bigger then "Num"
// if "i" is less then "Num" multiply "i" by 10 and increase count
// when the loop ends the number of count is the length of "Num".
}
int main(void){
unsigned int n, size=0;
printf("get the int:");
scanf("%u",&n);
/*the magic*/
for(int i = 1; n >= i; i*=10){
size++;
}
printf("the value is: %u \n", n);
printf("the size is: %u \n", size);
return 0;
}
#include <stdio.h>
int main(void){
int c = 12388884;
printf("length of integer is: %d",printf("%d",c));
return 0;
}

Resources