#include<stdio.h>
int main()
{
long ctr[100000],i;
float j;
long d[100000],T,h,o;
scanf("%ld",T);
printf("\n");
for(i=0; i<T; i++)
{
scanf("%ld",d[i]);
printf("\n");
for(h=d[i]; h<=0; h--)
{
j=h%10;
if(j==5)
{
ctr[i]++;
}
}
}
for(o=0; o<=i; o++)
{
printf("%ld\n",o);
}
return 0;
}
It's a program to find the number of trailing zeros of a factorial of a group of "T" numbers, input by the user.
What I have done is to divide each number by 10 and test if the number is 5. Then I decrement the number by 1 until it reaches 0. Each pair of 5*4 contributes one trailing 0.
Is the program consuming too much memory or is there another runtime error? This program is giving a runtime error, can anyone help?
A couple of observations:
long[100000] requires 400,000 bytes of stack assuming long is plain old 32 bits, 800,000 bytes if long is 64-bit. You have two such arrays, which might make your program hit operating system stack size limits.
The scanf() function requires pointers to where to store values it's reading in. You're not giving it pointers. As Paul R said in a comment.
Assuming positive numbers are input, the loop for(h=d[i]; h<=0; h--) will never run its body.
Hmm... This loop looks like the loop is going infinity.
for(h=d[i]; h<=0; h--)
Thus giving you a runtime error... Because the count is going negative, and your loops condition says continue until the value reaches less than or equal to zero, but it seems like, your value would never reach zero.
And for the scanf function, don't forget to use the & sign. Like this:
scanf("%ld", &sampleVariable);
That's the solution for your runtime error. :)
And also maybe you should use High Precision Variables, I think you need a higher precision more than the double datatype because you'll be dealing with huge amount of numbers.
See here for added info: http://www.nongnu.org/hpalib/
The loop is going infinity. Ensure that the count is not going negative or else you'll have a runtime error.
Related
First, I need to input N.
For example, from 1 to 5, there is 3 prime number: 2,3,5.
Now, I need to find prime numbers that consists only from odd numbers.
53 is it's example.
It's always easier to think about code like this if you partition different functionality off into different functions. You can, theoretically, interweave all the code together, to have code that's checking for prime numbers and odd digits at the same time, but it's much harder to write, read, understand, and debug, so unless there's some compelling reason to compress everything (like, maybe, efficiency), for everyday purposes it's much easier to keep things separate.
So although you haven't quite written your code that way yet, what I'm imagining is that we have a number n we're interested in checking. In your case it's the loop variable in your for(i = 2; i <= N; i++) loop. If you were just counting primes, you'd have
if(isprime(n))
count++;
Here I'm imagining that you have a separate function called isprime() that you can call to see if a number is prime. (It would contain the same kind of code you currently have for setting your isPrime variable to true or false.) And then, if you want to count how many of the prime numbers have only odd digits, you might go to something like this:
if(isprime(n)) {
count++;
if(has_only_odd_digits(n))
count2++;
}
Arranged this way, count will be the count of how many numbers were prime, and count2 will be the count of how many numbers were prime and had only odd digits. (Different arrangements are obviously possible to answer different variants of the question, like how many numbers had only odd digits, whether or not they were prime.)
And then the obvious question is: Where does the hypothetical has_only_odd_digits function come from? We'll have to write it ourselves, of course, but the nice thing is that while we're writing it, we'll only have to think about the problem of determining whether digits are even or odd; we won't have to worry about prime numbers at all.
So let's take a first cut at writing has_only_odd_digits. You had a version, sort of, in the code you originally posted:
int has_only_odd_digits(int n)
{
if(n % 2 == 0) /* if even */
return 0;
else return 1;
}
But this is wrong: it just tests whether the number n itself is even or odd. It will return "false" for 2 and 20 and 222, and it will return "true" for 3 and 13 and 13579, but it will also return "true" for 2461, since 2461 is odd, even though it happens to have mostly even digits. So for a working version of has_only_odd_digits we need something more like this:
int has_only_odd_digits(int n)
{
for(each digit d of n) {
if(d % 2 == 0)
return 0;
}
return 1;
}
This is pseudocode, not real C code yet. Notice that this time there's no else in the if statement. If we find an even digit, we're done. But if we find an odd digit, we can't necessarily return "true" yet — we have to check all the digits, and only return true" if none of the digits were even.
But the real question is, how do we get at those digits? An int variable is not represented internally by anything remotely like an array of its decimal digits. No, an int variable is an integer, a number, and the only way to get at its decimal-digit representation is to, literally, divide it repeatedly by 10.
So, fleshing out our code just a little bit more, we're going to have something like
int has_only_odd_digits(int n)
{
while(n != 0) {
int d = one digit of n;
if(d % 2 == 0)
return 0;
n = the rest of n, except for the digit d we just checked;
}
return 1;
}
And that's as far as I'm going to take it: I think you've got the idea by now, and in case this is a homework assignment, I'm not going to do all the work for you. :-) I'll note that there's also still a discrepancy to nail down between your question title and your problem description in the question: are you looking for prime numbers with odd digits, or prime digits? (And if the latter, I'm honestly not sure what to do with 1's, but that'll be a question for you and your instructor, I guess.)
But, in closing, I want to point out a couple of things: besides learning how to count primes with odd digits, I hope you've also also begun to appreciated two, much more general, related points:
If you break a complicated program up into separate functions, it's much easier to think about each function (each part of the problem) in isolation.
If you're not sure how to do something, often you can attack it in little steps, sort of a "successive refinement" approach, like I did with the several different versions of the has_only_odd_digits function here.
Now, it's true, you can't necessarily just break a complicated problem up into functions any old way, and when you're solving a problem by stepwise refinement, you have to choose the right steps. But, still, these are definitely valuable approaches, and with time and experience, you'll find it easier and easier to see how to break a big problem down into pieces you can handle.
#include <stdio.h>
int main(void) {
// single-line for-loop
for (int i = 0; i < 5; i--);
// delays to execute this syntax
printf("Hello\n");
return 0;
}
Why does it take around 10 seconds to print Hello in console after running it?
Notice that the use of a semicolon at the end of the For loop is intentionally given.
I've figured out how and why this happened..
It's because the range of int data type is from -2,147,483,648 to 2,147,483,647. "i" in this for loop is going from 0 to -2,147,483,648 (because of i--;) and after that when the value of "i" becomes 2,147,483,647 (because of limitations of data type's range and data overflow), hence making the condition (i<5;) false and the loop stops. After that the next statement (printf("Hello");) prints "Hello".
The whole process of the loop iterating 2 Billion times takes 10 seconds by my compiler to process and after that it prints the next call (which is printf("Hello");)
int i;
for(i=0;i<5;i--);
We don't know anything about your C implementation.
For more about the C language, see this reference and later the C11 standard n1570. Read also Modern C
My guess would be that you use a recent GCC compiler on a x86-64 computer. I recommend reading the documentation of your optimizing compiler, for GCC it is here. You could also need to read the documentation of your linker, so (on my Linux computer) of binutils.
If indeed that is the case, I recommend enabling all warning and debug info, so compile your code with gcc -Wall -Wextra -g. You are likely to get some warnings.
You are decrementing i. Assume that int are 32 bits. Then on the first loop, i is 0; on the second loop, i becomes -1 .... Your computer probably will loop 231 times. So about two billions loops.
Computers are fast, but not infinitely fast.
My recommendation: learn to use a debugger, such as GDB.
At last, <stdio.h> gives buffered input output. So learn to use fflush(3) and read of course the documentation of printf(3).
for(i=0;i<5;i--);
Well I don't know how you got Hello even after 10 seconds! Take a closer look at the for loop. It actually never ends because the i value is constantly decreasing and hence it will always be less than 5. So I suppose the process was terminated.
Now don't think that just because you added a semi colon after the for loop the for loop won't run. It will run. Looping will take place, its just that there is no code to execute. The semi colon will be considered as a null statement by the compiler. And once the condition will return false the compiler will move on to the next statement.
Please check whether the code is correct or not. I highly doubt that it is ++i and not --i
Since the decrement (i.e. i--) will be executed till infinity for i < 5 never meets, as soon as the iterating integer i reaches the minimum value that an integer could hold (i.e. -2,147,483,648) get overflowed and it instantly quits the loop at negative 2147483648-th iteration.
If you write something like this:
int i;
long long j = 0; // intentionally using to hold lesser than the value
// and integer could hold for debugging test
for(i = 0; i < 5; i--)
j = i;
printf("%d\n", j);
Then you'll get to know practically in which iteration the loop is quitting and the reason behind getting a few time to print Hello after that loop.
I wrote a small program to compute Fibonacci numbers:
#include <stdio.h>
int main()
{
int first, second, final;
first = 0;
second = 1;
printf("0\n1\n"); /* I know this is a quick fix, but the program still works */
while (final <= 999999999999999999) {
final = first + second;
first = second;
second = final;
printf("%d\n", final);
}
}
Is there any way to increase the speed in which this program computes these calculations? Could you possible explain the solution to me (if it exists)?
Thanks.
Of course it's possible! :)
First of all, please note you're using signed int for your variables, and max int on a 32 bit machine is 2,147,483,647 which is approx. 10^8 times smaller than the max number you're using, which is 999,999,999,999,999,999.
I'll recommend to change the max num to INT_MAX (You'll need to include "limits.h")
Edit:
In addition, as said in the comments to my answer, consider changing to unsigned int. you need only positive values, and the max number will be twice higher.
2nd Edit:
That being said, when final will reach the closest it can to the limit in the condition, the next time its promoted, it'll exceed INT_MAX and will result in an overflow. That means here, that the condition will never be met.
Better to just change the condition to the times you want the loop to run. Please note though, that any fibonacci number larger than the max numder that can be stored in your variable type, will result in an overflow.
Secondly, final isn't initialized. Write final = 0 to avoid errors.
I recommend turning on all the warnings in your compiler. It could catch many errors before they compile :)
Also, I see no reason not to initialize the variables when you declare them. The value is already known.
Now for the speed of the program:
I'm not sure to which extent you're willing to change the code, but the simplest change without changing the original flow, is to make less calls to printf().
Since printf() is a function that will wait for a system resource to become available, this is probably the most time consuming part in your code.
Maybe consider storing the output in a string, and lets say every 100 numbers print the string to the screen.
Try maybe to create a string, with a size of
(10 (num of chars in an int) + 1 (new line char) )* 100 (arbitrary, based on when you'll want to flush the data to the screen)
Consider using sprintf() to write to a string in the inner loop, and strcat() to append a string to another string.
Then, every 100 times, use printf() to write to the screen.
As already stated in other answers, you have obvious two problems. 1) The missing initialization of final and 2) that your loop condition will result in an endless loop due to 999999999999999999 being larger than any integer value.
The real problem here is that you use a fixed number in the condition for the while.
How do you know which number to use so that you actually calculates all the Fibonacci numbers possible for the used integer type? Without knowing the numbers in advance you can't do that! So you need a better condition for stopping the loop.
One way of solving this to check for overflow instead - like:
while (second <= (INT_MAX - first)) { // Stop when next number will overflow
The above approach prevents signed overflow by checking whether the next first + second will overflow before actually doing the first+second. In this way signed overflow (and thereby UB) is prevented.
Another approach is to use unsigned integers and deliberately make an overflow (which is valid for unsigned int). Using unsigned long long that could look like:
unsigned long long first, second, next;
first = 1;
second = 1;
printf("1\n1\n");
next = first + second;
while (next > second) { // Stop when there was an overflow
printf("%llu\n", next);
first = second;
second = next;
next = first + second;
}
Speed isn't your problem. You have an infinite loop:
while (final <= 999999999999999999) {
final has type int. Most likely int is 32-bit on your system, which means the maximum value it can hold is 2147483647. This will always be smaller than 999999999999999999 (which is a constant of type long long), so the loop never ends.
Change the datatype of your variables to long long and the loop will terminate after about 87 iterations. Also, you'll need to change your printf format specifier from %d to %lld to match the datatype printed.
Why are you asking this question?
If it's the intention to increase the performance, you might go for the formula of the n-th Fibonacci number, which is something like:
((1+v5)/2)^n + ((1-v5)/2)^n, something like that (v5 being the square root of 5).
If it's about learning to increase performance, you might do a code review or use performance diagnostics tools.
I am running this below 'C' program which has an infinite loop. I see the CPU reaching almost 99% using the 'top' command. Then suddenly the program stops. I was curious to know what rule in the system is causing it to stop.
I am running this under a docker image alpine:3.1 (+ some modules) and I just simply start its ash (alpine's bash).
Also, I can not find ulimit.
#include <stdio.h>
int main() {
int marks[10],i,n,sum=0;
printf("Enter number of students: ");
scanf("%d",&n);
for(i = 0; i < n; --i) {
//printf("Enter marks of student%d: ",i+1);
int c;
c = 5;
int a;
a = c;
}
return 0;
}
As you mention, you could expect this to produce an infinite loop, at least if n is positive.
The behaviour you're seeing instead is caused by your counter wrapping around: when it reaches INT_MIN, the result of --i is INT_MAX (at least, with GCC's default settings on Intel-style CPUs — this is not defined in C, see below) and i<n fails.
So your program uses 100% of one CPU while it counts down from 0 to INT_MIN, then wraps around to INT_MAX and stops.
You can add
printf("%d\n", i);
just before the return line to see the value of i when the loop exits.
Note that this is undefined behaviour in C... If you compile this with -O2, at least with GCC 5.3, the program never exits the loop, because the optimiser decides that the exit condition will never be reached, and compiles the loop as a tight infinite loop if n is positive (.L4: jmp .L4).
Your loop is not infinite per se. YOu have a termnation condition which can be reached - in principle. The CPU load occurs, just because the loop runs for (likely) >2000000000 iterations before it ends.
First of all, you don't check the result of scanf. If it failed, n is unspecified.
Worse, your code invokes undefined behaviour (UB) due to signed integer over-/underflow. You decrement i past the minimum representable int value INT_MIN. Note that C does not have arbitrary length integers like Python.
Undefined behaviour means anything can happen, all bets are off. In your case, it might wrap to the max. positive int INT_MAX, thus the comparison fails and the loop is exited. But this is nothing you can rely on!
From the text and rest of the code, you likely don't want to decrement i, but increment: i++, so it counts from 0 to n - 1. Note that you also should check n for a valid range and ask the use to enter a valid value again. For the example, a negative upper limit is useless (but it does also no harm).
#include<stdio.h>
int fact(int k)
{
int j,f=1;
for(j=1;j<=k;j++)
f*=j;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
scanf("%d",&t);
for(i=0;i<t;i++)
{
scanf("%d",&n[i]);
}
for(j=0;j<t;j++)
{
s[j]=fact(n[j]);
printf("%d \n",s[j]);
}
return 0;
}
You are asked to calculate factorials of some small positive integers.
Input
An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100.
Output
For each integer n given at input, display a line with the value of n!
Example
Sample input:
4
1
2
5
3
Sample output:
1
2
120
6
Your code will give correct results for the given test cases but that doesn't prove that your code works. It is wrong is because of integer overflow. Try to calculate 100! by your program and you'll see what's the problem.
My answer lacked details. I'll update this to add details for an answer to the question as it stands now.
C has limitations over the the maximum and minimum size that can be stored in a variable. For doing arbitrary precision arithmetic it is usually advisable to use a bignum library as PHIFounder has suggested.
In the present case however, the use of external libraries is not possible. In this case arrays can be used to store integers exceeding the maximum value of the integers possible. OP has already found this possibility and used it. Her implementation, however, can use many optimizations.
Initially the use of large arrays like that can be reduced. Instead of using an array of 100 variables a single variable can be used to store the test cases. The use of large array and reading in test cases can give optimization only if you are using buffers to read in from stdin otherwise it won't be any better than calling scanf for reading the test cases by adding a scanf in the for loop for going over individual test cases.
It's your choice to either use buffering to get speed improvement or making a single integer instead of an array of 100 integers. In both the cases there will be improvements over the current solution linked to, on codechef, by the OP. For buffering you can refer to this question. If you see the timing results on codechef the result of buffering might not be visible because the number of operations in the rest of the logic is high.
Now second thing about the use of array[200]. The blog tutorial on codechef uses an array of 200 elements for demonstrating the logic. It is a naive approach as the tutorial itself points out. Storing a single digit at each array location is a huge waste of memory. That approach also leads to much more operations leading to a slower solution. An integer can at least store 5 digits (-32768 to 32767) and can generally store more. You can store the intermediate results in a long long int used as your temp and use all 5 digits. That simplification itself would lead to the use of only arr[40] instead of arr[200]. The code would need some additional changes to take care of forward carry and would become a little more complex but both speed and memory improvements would be visible.
You can refer to this for seeing my solutions or you can see this specific solution. I was able to take the use down to 26 elements only and it might be possible to take it further down.
I'll suggest you to put up your code on codereview for getting your code reviewed. There are many more issues that would be best reviewed there.
Here, your array index should start with 0 not 1 , I mean j and ishould be initialized to 0 in for loop.
Besides, try to use a debugger , that will assist you in finding bugs.
And if my guess is right you use turbo C, if yes then my recommendation is that you start using MinGW or Cygwin and try to compile on CLI, anyway just a recommendation.
There may be one more problem may be which is why codechef is not accepting your code you have defined function to accept the integer and then you are passing the array , may be this code will work for you:
#include<stdio.h>
int fact(int a[],int n)// here in function prototype I have defined it to take array as argument where n is array size.
{
int j=0,f=1,k;
for (k=a[j];k>0;k--)
f*=k;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
setbuf(stdout,NULL);
printf("enter the test cases\n");
scanf("%d",&t); //given t test cases
for(i=0;i<t;i++)
{
scanf("%d",&n[i]); //value of the test cases whose factorial is to be calculated
}
for(j=0;j<t;j++)
{
s[j]=fact(&n[j],t);// and here I have passed it as required
printf("\n %d",s[j]); //output
}
return 0;
}
NOTE:- After the last edit by OP this implementation has some limitations , it can't calculate factorials for larger numbers say for 100 , again the edit has taken the question on a different track and this answer is fit only for small factorials
above program works only for small numbers that means upto 7!,after that that code not gives the correct results because 8! value is 40320
In c language SIGNED INTEGER range is -32768 to +32767
but the >8 factorial values is beyond that value so integer cant store those values
so above code can not give the right results
for getting correct values we declare the s[100] as LONG INT,But it is also work
only for some range