I was trying to make an array that contains Fibonacci numbers in C, but I got into trouble. I can't get all of the elements, and some of the elements are wrongly calculated, and I don't know where I am I going wrong.
#include <stdio.h>
int main(void){
int serie[]={1,1},sum=0,size=2;
while(size<=4000000){
serie[size]=serie[size-1]+serie[size-2];
printf("%d\n",serie[size-1]);
size+=1;
}
return 0;
}
Output:
1
2
4
6
11
17
28
45
73
118
191
309
500
809
1309
2118
3427
5545
8972
14517
23489
38006
61495
99501
160996
260497
421493
681990
1103483
1785473
2888956
4674429
7563385
12237814
19801199
32039013
51840212
83879225
135719437
219598662
355318099
574916761
930234860
1505151621
-1859580815
-354429194
2080957287
1726528093
-487481916
1239046177
751564261
1990610438
-1552792597
437817841
-1114974756
-677156915
-1792131671
1825678710
33547039
1859225749
1892772788
-542968759
1349804029
806835270
-2138327997
-1331492727
825146572
-506346155
318800417
-187545738
131254679
-56291059
74963620
18672561
93636181
112308742
205944923
318253665
524198588
842452253
1366650841
-2085864202
-719213361
1489889733
770676372
-2034401191
-1263724819
996841286
-266883533
729957753
463074220
1193031973
1656106193
-1445829130
210277063
-1235552067
-1025275004
2034140225
1008865221
-1251961850
-243096629
-1495058479
-1738155108
1061753709
-676401399
385352310
-291049089
94303221
-196745868
-102442647
-299188515
-401631162
-700819677
-1102450839
-1803270516
1389245941
-414024575
975221366
561196791
1536418157
2097614948
-660934191
--------------------------------
Process exited after 2.345 seconds with return value 3221225477
Press any key to continue . . .
I don't understand why it is giving that output.
int serie[]={1,1}
Declares an array of two elements. As the array has two elements and indices start from zero, it has valid indices - 0 and 1, ie. serie[0] is the first element and serie[1] is the second element.
int size=2;
while(..) {
serie[size]= ...
size+=1;
}
As size starts 2, the expression serie[2] = is invalid. There is no third element in the array and it writes to an unknown memory region. Executing such an action is undefined behavior. There could be some another variable there, some system variable, or memory of another program or it can spawn nasal demons. It is undefined.
If you want to store the output in an array, you need to make sure the array has enough elements to hold the input.
And a tip:
int serie[4000000];
may not work, as it will try to allocate 40000000 * sizeof(int), which assuming sizeof(int) = 4 is 15.2 megabytes of memory. Some systems don't allow to allocate that much memory on stack, so you should move to dynamic allocation.
You're having an integer overflow because the int size is ,at a certain leverl, not big enough to hold the numbers, so the number is wrapping round the size and giving false values.
Your program should be like:
#include <stdio.h>
int main(void){
long long unsigned series[100] = {1,1};
int size = 2;
while(size < 100){
series[size] = series[size-1] + series[size-2];
printf("%llu\n", series[size-1]);
size += 1;
}
return 0;
}
Although, size of long long unsigned is also limited, at a certain level, with such very big numbers in Fibonacci. So this will result in more correct numbers printed, but also will overflow at a certain level. It will overflow when the number exceeds this constant ULLONG_MAX declared in limits.h.
The problem with this code:
#include <stdio.h>
int main(void){
int serie[]={1,1},sum=0,size=2;
while(size<=4000000){
serie[size]=serie[size-1]+serie[size-2];
printf("%d\n",serie[size-1]);
size+=1;
}
return 0;
}
... is that it attempts to store a very long series of numbers (4 million) into a very short array (2 elements). Arrays are fixed in size. Changing the variable size has no effect on the size of the array serie.
The expression serie[size]=... stores numbers outside the bounds of the array every time it's executed because the only legal array index values are 0 and 1. This results in undefined behavior and to be honest you were lucky only to see weird output.
There are a couple of possible solutions. The one that changes your code the least is to simply extend the array. Note that I've made it a static rather than automatic variable, because your implementation probably won't support something of that size in its stack.
#include <stdio.h>
int serie[4000000]={1,1};
int main(void){
int size=2;
while(size<4000000){ // note strict less-than: 4000000 is not a valid index
serie[size]=serie[size-1]+serie[size-2];
printf("%d\n",serie[size-1]);
size+=1;
}
return 0;
}
The more general solution is to store the current term and the two previous terms in the series as three separate integers. It's a little more computationally expensive but doesn't have the huge memory requirement.
#include <limits.h>
#include <stdio.h>
int main(void)
{
int term0=0, term1=1, term2;
while(1)
{
if (term0 > INT_MAX - term1) break;// overflow, stop
term2 = term0 + term1;
printf("%d\n",term2);
term0 = term1;
term1 = term2;
}
return 0;
}
This also has the benefit that it won't print any numbers that have "wrapped around" as a result of exceeding the limits of what can be represented in an 'int`. Of course, you can easily choose another data type in order to get a longer sequence of valid output.
You have two problems:
You need to allocate more space in serie, as much as you are going
to use
Eventually the fib numbers will become too big to fit inside an integer, even a 64bit unsigned integer (long long unsigned), i think 90 or so is about max
See the modified code:
#include <stdio.h>
// Set maximum number of fib numbers
#define MAX_SIZE 90
int main(void) {
// Use 64 bit unsigned integer (can't be negative)
long long unsigned int serie[MAX_SIZE];
serie[0] = 1;
serie[1] = 1;
int sum = 0;
int size = 0;
printf("Fib(0): %llu\n", serie[0]);
printf("Fib(1): %llu\n", serie[1]);
for (size = 2; size < MAX_SIZE; size++) {
serie[size] = serie[size-1] + serie[size-2];
printf("Fib(%i): %llu\n", size, serie[size]);
}
return 0;
}
As you are only printing out the numbers, you don't actually have to store all of them
(only the two previous numbers), but it really doesn't matter if there's only 90.
Related
What is the problem with the following code? C compiler shows me error: Segmentation fault.
#include <stdio.h>
#include <math.h>
int main() {
int n = 4;
float A[n][n][n][n];
A[n][n][1][1] = 1;
A[n][n][1][2] = 0;
A[n][n][1][3] = -3;
A[n][n][1][4] = 0;
A[n][n][2][1] = 1;
A[n][n][2][2] = 0;
A[n][n][2][3] = -3;
A[n][n][2][4] = 0;
return 0;
}
All these assignments access memory outside the defined variable length array.
A[n][n][1][1]=1;
A[n][n][1][2]=0;
A[n][n][1][3]=-3;
A[n][n][1][4]=0;
A[n][n][2][1]=1;
A[n][n][2][2]=0;
A[n][n][2][3]=-3;
A[n][n][2][4]=0;
That is the valid range of indices for each dimension of the array is [0, n ). Thus the expression A[n] is invalid.
It seems you mean the following assignments
A[0][0][0][0]=1;
A[0][0][0][1]=0;
A[0][0][0][2]=-3;
A[0][0][0][3]=0;
A[0][0][1][0]=1;
A[0][0][1][1]=0;
A[0][0][1][2]=-3;
A[0][0][1][3]=0;
If you define an array of length N, the access to the last element is at the N-1 index, and the access to the first element is at index 0 because indexes start from 0 and end at N-1.
So your code should be like this:
#include<stdio.h>
#include<math.h>
#define N 4
int main() {
float A[N][N][N][N];
A[N-1][N-1][0][0]=1;
A[N-1][N-1][0][1]=0;
A[N-1][N-1][0][2]=-3;
A[N-1][N-1][0][3]=0;
A[N-1][N-1][1][0]=1;
A[N-1][N-1][1][1]=0;
A[N-1][N-1][1][2]=-3;
A[N-1][N-1][1][3]=0;
return 0;
}
Also, you're using a variable to define the length of your array, which is good only in the C99 standard and onwards. If you don't need a VLA (variable length array), you should use the #define instead.
int n=4;
float A[n][n][n][n];
A[n][n][1][1]=1;
is not valid in every C standard (read n1570 or better). You may want to code const int n=4; or #define n 4
(on cheap microcontrollers you might not even have enough stack space for 256 floats -> possible stack overflow)
And then, you always have a buffer overflow (read about undefined behavior). In A[x][x][1][1] the valid indexes are from x being 0 to x being 3 -that is n-1 - (not 4).
You might want to code
A[n-1][n-1][1][1] = 1;
but you should know that A[0][0][0][0] is being uninitialized. It may contain garbage (signalling NaN), and an hypothetical printf("%f\n", A[0][0][0][0]); could fail ....
I guess that Frama-C would have caught your mistake (I leave you to check that). Be aware of Rice's theorem.
I would initialize A with zeros (to ease debugging, and to have more reproducible runs) -after having corrected the buffer overflow-:
float A[n][n][n][n]={0.0};
I'm trying to write a function that when given an array and a value, it checks if the value is in that array. If it is there then keep finding a new unique random value before adding it to the array. This is what I have done so far but I think the problem is my lack of understanding of pointers. Here is what I have so far:
#include <stdio.h>
#include <stdlib.h>
int getNewIndex(int index, int *visitedPixels, int *visitedPixelsIndex);
int main() {
int *visitedPixels = malloc(2 * sizeof(int));
int *visitedPixelsIndex = 0;
srand(1);
int randIndex = rand() % 16, i;
printf("Initial randIndex = %d\n", randIndex);
for(i = 0; i < 16; i++) {
randIndex = getNewIndex(randIndex, visitedPixels, visitedPixelsIndex);
printf("randIndex[%d] = %d\n", i, visitedPixels[i]);
}
return 0;
}
int getNewIndex(int index, int *visitedPixels, int *visitedPixelsIndex) {
int i = 0;
while (i < *visitedPixelsIndex) {
(index == visitedPixels[i]) ? index = rand() % 16, i = 0 : i++;
}
visitedPixels[*visitedPixelsIndex] = index;
(*visitedPixelsIndex)++;
//(*visitedPixels) = realloc(visitedPixels, (*visitedPixelsIndex+1) * sizeof(int));
return index;
}
Any help would be appreciated.
Okay, so. I'm going to try to explain with a metaphor. Hopefully it helps rather than confusing more.
Imagine memory is a long board you can write numbers on. It takes an inch of board to write a small number. Bigger numbers can be represented by writing across more slots.
An array, in our metaphor, is just a contiguous length of board you can write stuff into. If you want an array of 5 integers, and each integer takes 4 inches, you'll need 20 inches of board for it. If you wanted to pass all these integers to a function, instead of copying them all across, you would instead write down how many inches from the end of the board your array is. That's what a pointer is. It's a number telling where something is.
When you called malloc( 2 * sizeof( int ) ), you requested for a segment of the board big enough for two integers, and you received how many inches from the end of the board that new segment is. So we've got 8 inches of board X inches from the end, with X being our pointer.
Incrementing a pointer says "increase this value to point at the next element of the underlying array". A int* will increase by 4, a pointer to a structure by the size of the structure plus any alignment offset the compiler has decided for it.
It does not increase the amount of storage.
If I have a pointer to two 8 inches of board, write a 4 inch number, increment the pointer to point 4 inches more in, write another 4 inch number and increment again, my pointer is now right after the last element of the array. If I write here, all bets are off. What was on the board after the array? Who knows. It could be anything. Maybe it was a different array. Maybe it was information for keeping track of what parts of the board have been handed out to the program. Maybe it was the end of my board and I'll write off the end. Writing to memory you haven't received permission to from the operating system is where signals for "segment violations", SIGSEGV, program failures come from.
You need to request more space up front, or bigger arrays as you need them. There's also a realloc that will do this too. And for all of them, you have to check if the call failed and terminate or otherwise recover appropriately.
Hopefully this is more helpful than confusing. Good luck :)
Need to find the index of a number, that may or may not be present in the array. I tried the below code:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *lhs, const void *rhs){
return ( *(long long*)lhs - *(long long*)rhs );
}
int main(){
int size = 9;
long long a[] = {16426799,16850699,17802287,18007499,18690047,18870191,18870191,19142027,19783871};
long long x = 17802287;
long long *p = (long long *)bsearch(&x, a, size, sizeof(long long), cmp);
if (p != NULL)
printf("%lld\n", p - a);
return 0;
}
The above code works if the number, in this case 17802287 is present in the array a, but fails if the number is not present in a, e.g. doesn't give any output for x=18802288, I would like to get the index i=5 in that case 5th element onwards the elements are greater than 18802288.
Also the actual array size will have number of elements more than 4 million, would the same code work?
Thanks for the help.
From the man page for bsearch:
The bsearch() function returns a pointer to a matching member of
the array, or NULL if no match is found. If there are multiple
elements that match the key, the element returned is unspecified.
So the function will return NULL if the element in question is not found. If you want to find the first element greater than or equal to the number in question, you'll need to roll your own function to do that.
One of the possible solution can be:
int i, outcome = -1;
for( i = 0; i < size; i++ )
{
if( x == a[i] )
{
outcome = i;
break;
}
}
printf("%d\n", outcome);
You need to write a function that does approximately this:
bsearch_geq (number array low high)
if low is equal to high return high
let halfway be average of low and high
if array[halfway] is equal to number then return halfway
if array[halfway] is greater than number then
return result of "bsearch_geq number array low halfway"
else
return result of "bsearch_geq number array halfway high"
That'll get you 99% of the way, I think, but I'll leave it as an exercise to the reader to figure out the corner cases. The main one I can see is what happens when you get down to just two numbers because the naive "average" may cause infinite recursion.
If you can have multiple occurrences of the same number in the array then you'll need to drop the if array[halfway] is equal]" line.
You should ensure your solution uses tail-recursion for efficiency, but it's not too critical as 4m data-entries only amounts to about 15 recursive calls.
Problem : Consider the following algorithm to generate a sequence of
numbers. Start with an integer n. If n is even, divide by 2. If n is
odd, multiply by 3 and add 1. Repeat this process with the new value
of n, terminating when n = 1. The input will consist of a series of
pairs of integers i and j, one pair of integers perline. All integers
will be less than 1,000,000 and greater than 0.
For each pair of
input integers i and j, output i, j in the same order in which they
appeared in the input and then the maximum cycle length for integers
between and including i and j. These three numbers should be separated
by one space, with all three numbers on one line and with one line of
output for each line of input.
sample input :
1 10
sample output:
1 10 20
so i wrote this :
#include <stdio.h>
#include <string.h>
struct line{int in1;int in2;int result;};
int cycle(int in);
int main(int argc, char *argv[]) {
int cycle(int in);
char c;
int firstIn=0;
struct line l[500] ;
int pointer=0;
while(2<3){
l[pointer].in1=0;
l[pointer].in2=0;
scanf("%u %u",&l[pointer].in1,&l[pointer].in2);
if(l[pointer].in1<1||l[pointer].in2<1){
break;
}
int maxCyc=0;
int j,m;
int min,max;
if(l[pointer].in1>l[pointer].in2){
max=l[pointer].in1;
min=l[pointer].in2;
}
else{
max=l[pointer].in2;
min=l[pointer].in1;
}
for(j=min;j<=max;j++){
m = cycle(j);
if(m>maxCyc)
maxCyc=m;
}
l[pointer].result=maxCyc;
printf("%d %d %d\n",l[pointer].in1,l[pointer].in2,l[pointer].result);
pointer++;
}
}
int cycle(int in){
int cyc = 1;
while(in>1){
if(in%2==0){
cyc++;
in=in/2;
}
else{
cyc++;
in=in*3+1;
}
}
return cyc;
}
Its completly ok but when you change while(in>1) in cycle method to while(in!=1) it gets much more slower. my question is why?!
Time when its while(in>1) : 0.683 sec
and when its while(in!=1) : I waited more than 5 min nothing
happened yet :)
for input : 1 1000000
there is no infinite loop or something because in cant get below 1 at all(for that it must be already 1) .
Best regards
When you call cycle with the input value 113383, the process eventually sets n to
827370449, and 3*827370449+1 is 2482111348, which is greater than the maximum signed int and is interpreted as -1812855948. So there's your first negative number where there should be no negative number.
If this process then eventually sets n to -2, it will loop infinitely between -2 and -1 from then on. There may be other loops I haven't considered.
If you were to use an unsigned int, there is a possibility (I haven't checked) that this too will overflow eventually, which will not result in a negative value but will result in an incorrect value, invalidating your results.
No matter what integer representation you use, it would probably be a good idea to compare n with (maximum-1)/3 at the top of each loop, where maximum is the largest possible positive value of your integer type, just to be sure you do not overflow.
As you told me it was a simple overflow problem thx everyone.
max int value is 2,147,483,647; So when i changed int cycle(int in) to int cycle(long long int in) my problem was solved.
i also figured it out that my first answer with while(in>1) was wrong.
When an integer overflow occurs,the value will go below 0 .That was the reason while(in!=1) was an infinte loop.
I was really tired that i didn't figure it out by myself. sorry for that :)
I'm working on Project Euler #14 in C and have figured out the basic algorithm; however, it runs insufferably slow for large numbers, e.g. 2,000,000 as wanted; I presume because it has to generate the sequence over and over again, even though there should be a way to store known sequences (e.g., once we get to a 16, we know from previous experience that the next numbers are 8, 4, 2, then 1).
I'm not exactly sure how to do this with C's fixed-length array, but there must be a good way (that's amazingly efficient, I'm sure). Thanks in advance.
Here's what I currently have, if it helps.
#include <stdio.h>
#define UPTO 2000000
int collatzlen(int n);
int main(){
int i, l=-1, li=-1, c=0;
for(i=1; i<=UPTO; i++){
if( (c=collatzlen(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
/* n != 0 */
int collatzlen(int n){
int len = 0;
while(n>1) n = (n%2==0 ? n/2 : 3*n+1), len+=1;
return len;
}
Your original program needs 3.5 seconds on my machine. Is it insufferably slow for you?
My dirty and ugly version needs 0.3 seconds. It uses a global array to store the values already calculated. And use them in future calculations.
int collatzlen2(unsigned long n);
static unsigned long array[2000000 + 1];//to store those already calculated
int main()
{
int i, l=-1, li=-1, c=0;
int x;
for(x = 0; x < 2000000 + 1; x++) {
array[x] = -1;//use -1 to denote not-calculated yet
}
for(i=1; i<=UPTO; i++){
if( (c=collatzlen2(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
int collatzlen2(unsigned long n){
unsigned long len = 0;
unsigned long m = n;
while(n > 1){
if(n > 2000000 || array[n] == -1){ // outside range or not-calculated yet
n = (n%2 == 0 ? n/2 : 3*n+1);
len+=1;
}
else{ // if already calculated, use the value
len += array[n];
n = 1; // to get out of the while-loop
}
}
array[m] = len;
return len;
}
Given that this is essentially a throw-away program (i.e. once you've run it and got the answer, you're not going to be supporting it for years :), I would suggest having a global variable to hold the lengths of sequences already calculated:
int lengthfrom[UPTO] = {};
If your maximum size is a few million, then we're talking megabytes of memory, which should easily fit in RAM at once.
The above will initialise the array to zeros at startup. In your program - for each iteration, check whether the array contains zero. If it does - you'll have to keep going with the computation. If not - then you know that carrying on would go on for that many more iterations, so just add that to the number you've done so far and you're done. And then store the new result in the array, of course.
Don't be tempted to use a local variable for an array of this size: that will try to allocate it on the stack, which won't be big enough and will likely crash.
Also - remember that with this sequence the values go up as well as down, so you'll need to cope with that in your program (probably by having the array longer than UPTO values, and using an assert() to guard against indices greater than the size of the array).
If I recall correctly, your problem isn't a slow algorithm: the algorithm you have now is fast enough for what PE asks you to do. The problem is overflow: you sometimes end up multiplying your number by 3 so many times that it will eventually exceed the maximum value that can be stored in a signed int. Use unsigned ints, and if that still doesn't work (but I'm pretty sure it does), use 64 bit ints (long long).
This should run very fast, but if you want to do it even faster, the other answers already addressed that.