Calculating unsigned number from binary numbers, using arrays and functions - c

I'm having a difficult time trying to calculate a number through an array that I have that contains only 0's and 1's. I have built a function that multiplies the exponent for each number but I'm having a bit of difficulty.
The problem is that I run into a loop that calculates all of the exponents of 2 instead of running 3 times, so if I'm trying to calculate 0000000000000000000000000000111 (which supposed to run 3 times) I get 1,2,4,8,16,32,64...4194304... and all of that 3 times.
My code is:
for(int i = 31; i > 0; i--){
if(EndArray[i] == 1){
for(x = 0; x < 30 ; x++){
UnsignedArray[30-x] = ExpoFunction(x);
}
}
}
ExpoFunction is:
int ExpoFunction(int x){
int result = 1;
for(int i = 0 ; i < x ; i++){
result *= 2;
}
return result;
}
EndArray is an array that contains 32 numbers of 0's and 1's. example: 0000000000000000000000000000111 which supposed to be 7.
At the end of this, I want to put everything in a new array which called UnsignedArray and then to sum all of UnsignedArray's numbers together.
Any ideas whats wrong or a better way?

You want to store all exponents in UnsignedArray, then sum all value in this array to have the decimal number, right ? If i am not wrong, your for loop should change to:
for(int i = 30; i >= 0; i--){ // should run from 30 to 0, not from 31 to 1
if(EndArray[i] == 1){
// just store one time, not using for loop of x as you did in your code.
UnsignedArray[30-i] = ExpoFunction(30-i);
printf("%d\n", UnsignedArray[30-i]); // if you want to test the value.
}
}
The main function for testing:
int main()
{
int EndArray[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1};
unsigned int UnsignedArray[31] = {0};
for(int i = 30; i >= 0; i--){
if(EndArray[i] == 1){
UnsignedArray[30-i] = ExpoFunction(30-i);
printf("%u\n", UnsignedArray[30-i]);
}
}
unsigned int sum = 0;
for(int i = 0; i < 31; i++) {
sum += UnsignedArray[i];
}
printf("decimal: %u", sum);
return 0;
}
The output:
1
2
4
decimal: 7

Related

How to Optimise my code that computes the sum of all from less than 2 million

I've tried this problem from Project Euler where I need to calculate the sum of all primes until two million.
This is the solution I've come up with -
#include <stdio.h>
int main() {
long sum = 5; // Already counting 2 and 3 in my sum.
int i = 5; // Checking from 5
int count = 0;
while (i <= 2000000) {
count = 0;
for (int j = 3; j <= i / 2; j += 2) {
// Checking if i (starting from 5) is divisible from 3
if (i % j == 0) { // to i/2 and only checking for odd values of j
count = 1;
}
}
if (count == 0) {
sum += i;
}
i += 2;
}
printf("%ld ", sum);
}
It takes around 480 secs to run and I was wondering if there was a better solution or tips to improve my program.
________________________________________________________
Executed in 480.95 secs fish external
usr time 478.54 secs 0.23 millis 478.54 secs
sys time 1.28 secs 6.78 millis 1.28 secs
With two little modifications your code becomes magnitudes faster:
#include <stdio.h>
#include <math.h>
int main() {
long long sum = 5; // we need long long, long might not be enough
// depending on your platform
int i = 5;
int count = 0;
while (i <= 2000000) {
count = 0;
int limit = sqrt(i); // determine upper limit once and for all
for (int j = 3; j <= limit; j += 2) { // use upper limit sqrt(i) instead if i/2
if (i % j == 0) {
count = 1;
break; // break out from loop as soon
// as number is not prime
}
}
if (count == 0) {
sum += i;
}
i += 2;
}
printf("%lld ", sum); // we need %lld for long long
}
All explanations are in the comments.
But there are certainly better and even faster ways to do this.
I ran this on my 10 year old MacPro and for the 20 million first primes it took around 30 seconds.
This program computes near instantly (even in Debug...) the sum for 2 millions, just need one second for 20 millions (Windows 10, 10 years-old i7 # 3.4 GHz, MSVC 2019).
Note: Didn't had time to set up my C compiler, it's why there is a cast on the malloc.
The "big" optimization is to store square values AND prime numbers, so absolutely no impossible divisor is tested. Since there is no more than 1/10th of primes within a given integer interval (heuristic, a robust code should test that and realloc the primes array when needed), the time is drastically cut.
#include <stdio.h>
#include <malloc.h>
#define LIMIT 2000000ul // Computation limit.
typedef struct {
unsigned long int p ; // Store a prime number.
unsigned long int sq ; // and its square.
} prime ;
int main() {
prime* primes = (prime*)malloc((LIMIT/10)*sizeof(*primes)) ; // Store found primes. Can quite safely use 1/10th of the whole computation limit.
unsigned long int primes_count=1 ;
unsigned long int i = 3 ;
unsigned long long int sum = 0 ;
unsigned long int j = 0 ;
int is_prime = 1 ;
// Feed the first prime, 2.
primes[0].p = 2 ;
primes[0].sq = 4 ;
sum = 2 ;
// Parse all numbers up to LIMIT, ignoring even numbers.
// Also reset the "is_prime" flag at each loop.
for (i = 3 ; i <= LIMIT ; i+=2, is_prime = 1 ) {
// Parse all previously found primes.
for (j = 0; j < primes_count; j++) {
// Above sqrt(i)? Break, i is a prime.
if (i<primes[j].sq)
break ;
// Found a divisor? Not a prime (and break).
if ((i % primes[j].p == 0)) {
is_prime = 0 ;
break ;
}
}
// Add the prime and its square to the array "primes".
if (is_prime) {
primes[primes_count].p = i ;
primes[primes_count++].sq = i*i ;
// Compute the sum on-the-fly
sum += i ;
}
}
printf("Sum of all %lu primes: %llu\n", primes_count, sum);
free(primes) ;
}
Your program can easily be improved by stopping the inner loop earlier:
when i exceeds sqrt(j).
when a divisor has been found.
Also note that type long might not be large enough for the sum on all architectures. long long is recommended.
Here is a modified version:
#include <stdio.h>
int main() {
long long sum = 5; // Already counting 2 and 3 in my sum.
long i = 5; // Checking from 5
while (i <= 2000000) {
int count = 0;
for (int j = 3; j * j <= i; j += 2) {
// Checking if i (starting from 5) is divisible from 3
if (i % j == 0) { // to i/2 and only checking for odd values of j
count = 1;
break;
}
}
if (count == 0) {
sum += i;
}
i += 2;
}
printf("%lld\n", sum);
}
This simple change drastically reduces the runtime! It is more than 1000 times faster for 2000000:
chqrlie> time ./primesum
142913828922
real 0m0.288s
user 0m0.264s
sys 0m0.004s
Note however that trial division is much less efficient than the classic sieve of Eratosthenes.
Here is a simplistic version:
#include <stdio.h>
#include <stdlib.h>
int main() {
long max = 2000000;
long long sum = 0;
// Allocate an array of indicators initialized to 0
unsigned char *composite = calloc(1, max + 1);
// For all numbers up to sqrt(max)
for (long i = 2; i * i <= max; i++) {
// It the number is a prime
if (composite[i] == 0) {
// Set all multiples as composite. Multiples below the
// square of i are skipped because they have already been
// set as multiples of a smaller prime.
for (long j = i * i; j <= max; j += i) {
composite[j] = 1;
}
}
}
for (long i = 2; i <= max; i++) {
if (composite[i] == 0)
sum += i;
}
printf("%lld\n", sum);
free(composite);
return 0;
}
This code is another 20 times faster for 2000000:
chqrlie> time ./primesum-sieve
142913828922
real 0m0.014s
user 0m0.007s
sys 0m0.002s
The sieve approach can be further improved in many ways for larger boundaries.

Armstrong number program in C returns wrong value

I am writing a program to see if a user entered number is Armstrong or not, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int x = 0;
printf("Enter a natural number: ");
scanf("%d", &x);
int ans = x;
// Digit Counter
int counter = 0; //Variable for number of digits in the user entered number
int b = x; //For each time number can be divided by 10 and isnt 0
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
++counter;
//Digit Counter
int sum = 0;
// Digit Finder
int D;
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
if (sum == ans){
printf("%d is a Armstrong number! :)", ans);
}else
printf("%d is not an Armstrong number :(", ans);
//Digit Finder
return 0;
}
My problem is that the program works fine apart from one point, when the program is given a Armstrong number which does not start with 1 then it behaves normally and indicates if it is an Armstrong number or not, but when i input a Armstrong number which start with 1 then it will print out the Armstrong number but -1.
For example: If i input something such as 371 which is an Armstrong number it will show that it is an Armstrong number. However if i input 1634 it will output 1633 which is 1 less than 1634.
How can i fix this problem?, also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
How can I fix this problem.
You know the number of iterations you want to make once you have calculated the digit count. So instead of looping till you reach the value of x:
for (int j = 1; j <= x; j++){
use the digit counter instead:
for (int j = 1; j <= counter; j++) {
also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
There's a number of things you can do to improve your code.
First and foremost, any piece of code should be properly indented and formatted. Right now your code has no indenting, which makes it more difficult to read and it just looks ugly in general. So, always indent your code properly. Use an IDE or a good text editor, it will help you.
Be consistent in your code style. If you are writing
if (some_cond) {
...
}
else
//do this
It is not consistent. Wrap the else in braces as well.
Always check the return value of a function you use, especially for scanf. It will save you from many bugs in the future.
if (scanf("%d", &x) == 1)
//...all OK...
else
// ...EOF or conversion failure...
exit(EXIT_FAILURE);
Your first for loop will iterate x times uselessly. You can stop when you know that you have hit 0:
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b == 0){
break;
}
counter += 1;
}
C has ++ operator. Use that instead of doing counter += 1
int D; you create this, but don't initialize it. Always initialize your variables as soon as possible
C has const qualifier keyword, which makes a value immutable. This makes your code more readable, as the reader can immediately tell that this value will not change. In your code, you can change ans variable and make it a const int because it never changes:
const int ans = x;
Use more descriptive names for your variables. ans, D don't tell me anything. Use proper names, so that the reader of your code can easily understand your code.
These are some of the things that in my opinion you should do and keep doing to improve your code and coding skills. I am sure there can be more things though. Keep your code readable and as simple as possible.
The condition in this loop
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
does not make sense because there will be numerous redundant iterations of the loop.
For example if x is equal to 153 that is contains only 3 digits the loop will iterate exactly 153 times.
Also additional increment of the variable counter after the loop
++counter;
makes the code logically inconsistent.
Instead of the loop you could write at least the following way
int counter = 0;
int b = x;
do
{
++counter;
} while ( b /= 10 );
This loop iterates exactly the number of times equal to the number of digits in a given number.
In this loop
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
it seems you did not take into account that the variable x is decreased inside the body of the loop
x /= 10; // Divides user entered number by 10 to get rid of digit found
So the loop can interrupt its iterations too early. In any case the condition of the loop again does not make great sense the same way as the condition of the first loop and only adds a bug.
The type of used variables that store a given number should be unsigned integer type. Otherwise the user can enter a negative number.
You could write a separate function that checks whether a given number is an Armstrong number.
Here you are.
#include <stdio.h>
int is_armstrong( unsigned int x )
{
const unsigned int Base = 10;
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= Base );
unsigned int sum = 0;
tmp = x;
do
{
unsigned int digit = tmp % Base;
unsigned int power = digit;
for ( size_t i = 1; i < n; i++ ) power *= digit;
sum += power;
} while ( ( tmp /= Base ) != 0 && !( x < sum ) );
return tmp == 0 && x == sum;
}
int main(void)
{
unsigned int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407,
1634, 8208, 9474, 54748, 92727, 93084, 548834
};
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%u is %san Armstrong number.\n", a[i], is_armstrong( a[i] ) ? "": "not " );
}
return 0;
}
The program output is
0 is an Armstrong number.
1 is an Armstrong number.
2 is an Armstrong number.
3 is an Armstrong number.
4 is an Armstrong number.
5 is an Armstrong number.
6 is an Armstrong number.
7 is an Armstrong number.
8 is an Armstrong number.
9 is an Armstrong number.
153 is an Armstrong number.
370 is an Armstrong number.
371 is an Armstrong number.
407 is an Armstrong number.
1634 is an Armstrong number.
8208 is an Armstrong number.
9474 is an Armstrong number.
54748 is an Armstrong number.
92727 is an Armstrong number.
93084 is an Armstrong number.
548834 is an Armstrong number.
Please remove j++ from 2nd loop for (int j = 1; j <= x; j++)
I tried this:
void armstrong(int x)
{
// count digits
int counter = 0, temp = x, sum = 0;
while(temp != 0)
{
temp = temp/10;
++counter; // Note: pre increment faster
}
// printf("count %d\n",counter);
temp = x;
while(temp != 0)
{
sum += pow(temp % 10, counter);
temp = temp/10;
}
// printf("sum %d\n",sum);
if(x == sum)
{
printf("Armstrong\n");
}
else
{
printf("No Armstrong\n");
}
}
int main(){
armstrong(371);
armstrong(1634);
return 0;
}
Let's take this and add the ability to handle multiple numeric bases while we're at it. Why? BECAUSE WE CAN!!!! :-)
#include <stdio.h>
#include <math.h>
double log_base(int b, double n)
{
return log(n) / log((double)b);
}
int is_armstrong_number(int b, /* base */
int n)
{
int num_digits = trunc(log_base(b, (double)n)) + 1;
int sum = 0;
int remainder = n;
while(remainder > 0)
{
sum = sum + pow(remainder % b, num_digits);
remainder = (int) (remainder / b);
}
return sum == n;
}
int main()
{
printf("All the following are valid Armstrong numbers\n");
printf(" 407 base 10 - result = %d\n", is_armstrong_number(10, 407));
printf(" 0xEA1 base 16 - result = %d\n", is_armstrong_number(16, 0xEA1));
printf(" 371 base 10 - result = %d\n", is_armstrong_number(10, 371));
printf(" 1634 base 10 - result = %d\n", is_armstrong_number(10, 1634));
printf(" 0463 base 8 - result = %d\n", is_armstrong_number(8, 0463));
printf("All the following are NOT valid Armstrong numbers\n");
printf(" 123 base 10 - result = %d\n", is_armstrong_number(10, 123));
printf(" 0x2446 base 16 - result = %d\n", is_armstrong_number(16, 0x2446));
printf(" 022222 base 8 - result = %d\n", is_armstrong_number(8, 022222));
}
At the start of is_armstrong_number we compute the number of digits directly instead of looping through the number. We then loop through the digits of n in base b, summing up the value of the digit raised to the number of digits in the number, for the given numeric base. Once the remainder hits zero we know there are no more digits to compute and we return a flag indicating if the given number is an Armstrong number in the given base.

Turn the flag on when the digits shows twice in a number - C

Without using an array.. How can I manage to turn a flag from 1 to 0 if there is the same digit twice or more in a number?
take it as if they are all integers, the temp & temp2 are the same number which is a 4 digit number
for(i = 0; i < 4; i++) //if a digits shows twice
{
n = temp % 10;
for(k = 0; k <= 6; k++)
{
if(n == temp2 % 10)
{
counter++;
}
temp2 /= 10;
}
temp /= 10;
if(counter > 1)
{
flag = 0;
}
counter = 0;
}
The result is that just it doesn't work.. something is not working
You take the least significant digit and check if it is present in the rest of the number. If it is found, you're done. If it is not found, you divide the number by 10 and repeat the process. Example:
n = 123456789;
step 1: Is 9 present in 12345678
step 2: Is 8 present in 1234567
step 3: Is 7 present in 123456
.. and so on ..
So first you write a function that can tell whether a number contains a specific digit. The function could look like:
int contains_digit(int number, int digit)
{
while(number)
{
if ((number % 10) == digit) return 0; // Return zero when found
number /= 10;
}
return 1; // Return one if not found
}
Then you call that function for all digits in the original number and tests the digit to the number divided by 10. For instance if the number is 1234, you call the function like:
contains_digit(123, 4)
contains_digit(12, 3)
contains_digit(1, 2)
That can be something like:
int main( void )
{
int n = 12434;
int flag = 1;
while(n && flag)
{
flag = contains_digit(n/10, n % 10);
n /= 10;
}
printf("flag is %d\n", flag);
return 0;
}

My C code is not working

I'm so confused here. Why this code of mine doesn't work as it SHOULD be..
Here's the code:
void print(int x) {
x = 140;
int i,total, length, value;
if (x < 10){
value = 0;
}
else {
int sum = 1;
for (i = 0 ; i < 10 ; i++){
total = 10 * sum;
sum = total;
length = x / total;
if (length < 10 && 1 <= length){
value = i+1;
break;
}
}
}
value = pow(10,value);
printf("%d\n",value);
}
Let me explain how the code should works first:
It takes an integer x and print out the highest power of 10 value it can be divided by.
So if X = 80, it should print 10 and if x = 12435, it should print 10000.
But this doesn't work with my code perfectly... if x = 140, it prints 99 but. if x = 1400, it prints 1000 then again, if x = 14000 it prints 9999 and if x = 140000 it prints 100000 and the sequence continues...
I've already tried exactly the same code in Java and it works perfectly!!
Why does it not works in C??
pow() is returning an double value, which you are casting to an integer. So instead of rounding it will be truncated.
You should try
value = round(pow(10,value));

Printing to output: integer as sum of powers of 2

I had an exam, and I've been struggling ever since.
You have an array of integers(ex. 13, 6, 21, 4), and I need to make an output that looks like:
13 = 2^3 + 2^2 + 2^0
6 = 2^2 + 2^1
21 = 2^4 + 2^2 + 2^0
4 = 2^2
here's what i've got so far.
#include <stdio.h>
#define MAX 100
int main() {
int niz[MAX], nizb, n, i, ones, k;
while(1) {
printf("Array length: ");
scanf("%d", &n);
if (n<=0 || n>MAX) break;
printf("Array elements: ");
for(i=0;i<n;i++){
scanf("%d", &niz[i]);
if (niz[i] <=0) {
printf("Error! Wrong value. Enter new one: ");
scanf("%d", &niz[i]);
}
}
for(i=0;i<n;i++) {
nizb = niz[i];
ones = 0;
for(k=0; k < 16; k++) {
//What should i do here?
}
}
}
}
I'm stuck here. I dont know how many bits should i use, and how does C sees those bits of integer. I'm using var 'k' to add to a string that is in format '2^3 + 2^2 ...', where k is the value of 'for' iteration. I have made an assumption that length of the integer is 16, but im really not sure since we do this on a sheet of paper.
I want to say BIG THANKS TO EVERYONE!!!
You can calculate how many bits to use by using the sizeof operator and CHAR_BIT:
int bitsPerInt = sizeof(int) * CHAR_BIT;
CHAR_BIT is definied in limits.h.
After you have that limit, you can use the bitwise & operator to extract each bit:
for (k = bitsPerInt - 1; k >= 0; k--)
{
if (nizb & (1U << k))
// output
else
// don't
}
I'll leave the details up to you.
Aside: It looks like you're trying to use niz as an array, but you haven't declared it as one. Does this code even compile? Also, the return value of main should be int.
Not sure what this has to do with twos-complement (which is a particular way of representing negative numbers). What you are trying to do is express an integer as a sum of powers of 2, apparently. Here's the way I'd do it, which isn't necessarily better or worse than the other answers...
void powersum(int n)
{ int powers[sizeof(int) << 3];
int i;
char *sep = "";
printf("%d = ", n);
powers[0] = 0;
for (i = 0; n; n >>= 1, ++i)
powers[i] = n & 1;
while (--i >= 0)
{ if (powers[i])
{ printf("%s2^%d", sep, i);
sep = " + ";
}
}
printf("\n");
}
EDIT: Here's another version that doesn't use the stack-allocated array, but as a tradeoff has to go around the loop more (once for each bit, as opposed to only looping until the highest 1-bit is found):
void powersum2(int n)
{ int i = (sizeof(int) << 3) - 2;
int m = 1 << i;
char *sep = "";
printf("%d = ", n);
while (m)
{ if (n & m)
{ printf("%s2^%d", sep, i);
sep = " + ";
}
m >>= 1;
--i;
}
printf("\n");
}
This is complete conjecture, since I'm not really good with math, but I think I'd go about it like this:
int potency = 0, base = 1;
while(base < NumberInQuestion) {
base *= 2;
++potency;
}
After the loop finishes, you'll know the highest potency which still fits into 'Number'.
Number -= base/2; //Removes the base you just calculated from the number.
printf("2^%d", potency);
Rinse and repeat, until Number falls to 0, which should be at 2^0 at latest.
For your use-case, the code may look somewhat like this:
for(i=0; i < n; ++i) {
int Number = niz[i];
while(Number > 0) {
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
Number -= base/2; //Reverts the last step you made, making the 'base' smaller than 'Number'.
printf("2^%d", potency);
}
}
There's a possible alternative, which can give you a more complete picture of things and will save you iterations. For this we use a two-step process.
for(i=0; i < n; ++i) {
int Number = niz[i];
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
base /= 2; //Reverses the last iteration.
//At this point, we know the maximum potency, which still fits into the number.
//In regards of base 2, we know the Most Significant Bit.
while(base > 0) {
Number -= base; //Removes the MSD (Most significant digit)
printf("2^%d", potency); //Prints your '1'.
while(base > Number) { //Executes at least once.
base /= 2; //Goes back one potency. (Ends at '0' latest.)
--potency; //For each potency (except for first), it's a '0'.
}
}
}
quotient = niz[i];
int k=0,c[MAX];
while(quotient!=0){
binaryNumber[i++]= quotient % 2; //this will convert your numbers to binary form
quotient = quotient / 2; //and store in reverse in array
}
for(j = 0 ;j<i;j++)
{
if(binaryNumber[j]==1) */e.g binary of 4 is stored in array as 001 ie 1 atpos2*/
{ c[k]=j;
k++;}
}
while(k--)
printf("2^%d +",c[k]);
If you can tolerate a GCC-dependency, a hack on #twalberg's solution get's really nice and small ;)
void powersum(int n)
{
char *sep = "";
printf("%d = ", n);
while (n) {
int pos = 31 - __builtin_clz(n);
printf("%s2^%d", sep, pos);
sep = " + ";
n ^= 1 << pos;
}
printf("\n");
}

Resources