Sum of multiple float points number - c

I write a algorithm to get the sum of float points number, and this algorithm works perfect for integer but when I applied to float points, the sum I got is a negative number. however my array of float points does only have positive float points number. here I post my code, thank you for checking it.
static unsigned int do_heap_sum(double ary[], unsigned int n,
double *result)
{
unsigned int j;
int counter=0;
double sum=0;
double min;
while(n>counter){
make_heap(ary,n);
min=ary[0];
sum=sum+min;
for(j=1;j<n;j++){
ary[j-1]=ary[j];
}
counter=counter+1;
}
*result=sum;
//exit(EXIT_FAILURE);
return 0;
}
in this code, I use the make_heap to find the min. do you think this has problem? (this make_heap works perfectly with integers extracting the min of array).
thanks again.

In your code, you want to calculate sum of the heap which stored in double[], so make_heap is superfluous, a simple loop is enough.
Make sure double is big enough to save the sum.
For ary[j-1] = ary[j] in for(j=1;j<n;j++), why not just swap ary[0] and ary[n - counter - 1] then adjust the heap in next loop, it's much cheaper.

My wild guess is that you used an integer version of make_heap:
void make_heap(int *ary,size_t n);
instead of a double precision float version:
void make_double_heap(double *ary,size_t n);
Otherwise, I notice that you sort a heap of size n, n times: that's too much work. What happens when some elements of ary are duplicated ?
You could rewrite the loop:
static unsigned int do_heap_sum(double ary[], unsigned int n,
double *result)
{
unsigned int counter=0;
double sum=0;
double min;
while(n>counter){
make_double_heap(ary+counter,n-counter);
min=ary[counter];
sum=sum+min;
counter=counter+1;
}
*result=sum;
return 0;
}

Related

Weird bug in C: Different results to the same function sometimes right sometimes wrong

So I am trying to run this code where I calculate the mean and median in 2 functions. When I use these functions in my main function and run my program, sometimes it gives me the right answer and sometimes it gives me some random numbers for the mean even though I run the exact same code. Can somebody explain this behavior to me?
Any help is appreciated.
float mean(int *numbers, int n){
int i=0;
float solution;
float tmp_m;
for(i=0; i<n; i++){
tmp_m=(float)numbers[i]+tmp_m;
}
solution=tmp_m/((float)n);
return solution;
}
float median(int *numbers, int n){
float median;
float median_b;
int index;
int index_b;
if(n % 2 == 1){
index=n/2;
median= (float)numbers[index];
return median;
}else if (n % 2 == 0){
index_b=n/2;
float tmp_median;
tmp_median= (float)numbers[index_b] + (float)numbers[index_b-1];
median_b=tmp_median/((float)2);
return median_b;
}
}
#include <stdio.h>
int main () {
int array[6]={0,2,3,4,0,5};
int n=6;
float result=mean(array, n);
float result_median=median(array, n);
printf("%f\n%f\n", result, result_median);
return 0;
}
The variable tmp_m is left uninitialized and it gives you random values.
So, replace float tmp_m; with float tmp_m = 0; in the mean function.
You haven’t initialised tmp_m to zero before using it.
Your tmp_m is not initialized to 0, so it starts out as a random number, which results in an incorrect result

C can't find 10th decimal digit of sqrt{2}

My code for finding 10th decimal digit of square root of 2.
#include <stdio.h>
unsigned long long int power(int a, int b);
unsigned long long int root(int a);
int main()
{
int n;
n=10;
printf("%llu \n",root(n));
return 0;
}
unsigned long long int power(int a, int b)
{
int i;
unsigned long long int m=1;
for (i=1;i<=b;i++)
{
m*=a;
}
return m;
}
unsigned long long int root(int a)
{
unsigned long long int c=1;
int counter=1;
while(counter<=a)
{
c*=10;
while(power(c,2)<=2*power(10,2*counter))
{
c++;
}
c-=1;
counter++;
}
return c;
}
I have tried the same algorithm in python. It can find the 10th decimal digit of $sqrt{2}$ immediately.
However, while doing C, I have waited for 10 mins but without a result.
Python handles big numbers for you. [1]
Although, as you say that you are getting the answer "immediately", your algorithm in python is not probably the same as the one you used in C.
#bruno's answer already explains why you are not getting the expected results in C.
[1] Handling very large numbers in Python
Exceed the range that the data can represent. when counter is equal to 10,2*power(10,2*counter) exceeds the range that unsigned long long int can represent. Python supports large number calculations, unlimited digits
you have overflow(s)
when counter values 10 you try to compute power(10,20) but even long long on 64 bits are not enough large, so you loop in
while(power(c,2)<=2*power(10,2*counter)){
c++;
}
for a long time (may be without ending)
Having long long on 64 bits allows to compute the result for n valuing up to 9

Riemann Zeta function in C for negative's odd reals

I'm trying to code the Riemann Zeta function in C but I'm having quite issues with the negative odds one. Since Even negatives are 0 by definition. Only for Real numbers the function, not complex. So 0..1 it's undefined. I know it's some math error I'm doing, but I started today to read about this function and I'm trying to learn.
https://en.wikipedia.org/wiki/Riemann_zeta_function
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double zeta(double s, long long int n)
{
double p=0.0;
if(s<0 && fmod(s,2)==0)
{
return p;
}
if(s==0) { return -0.5;}
if(s>0 && s<=1)
{
puts("Undefined. ");
exit(-1);
}
long long int i;
for(i=n; i>0; i--)
{
p+=pow(i,-s);
}
return p;
}
int main()
{
double s;
puts("Enter real number to Zeta function: ");
scanf("%lf",&s);
printf("\n%.15lf",zeta(s,1000000));
return 0;
}
It's just a sketch... Nothing professional here!
example: zeta(-5) = -0.003968253968253
it's giving 1.036927755143338...
I'm only having issues with NEGATIVE REAL ones...
I'm on Windows 10, Codeblocks with GCC.
The code was update with the #NPE contributions but still not working for negative real odds...
I did not participate in comments, sorry.
following the definition of the zeta-function the simple way of coding is (I just changed s to -s from your code, and added the 'level of convergence n' as a parameter)
double zeta_simple(double s, long long int n)
{
double p=0.0;
long long int i;
for(i=1; i<=n; i++)
{
p+=pow(i,-s);
}
return p;
}
However the problem is that you start adding the "big" numbers before the "small" and soon you will hit underflow operation. So what you want to do is
double zeta(double s, long long int n)
{
double p=0.0;
long long int i;
for(i=n; i>0; i--)
{
p+=pow(i,-s);
}
return p;
}
you can test convergence with s=2 which converges to PI^2/6.0 and s=4 which converges to PI^4/90.0
#define PI 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679L
int main()
{
long long int n;
for (long long int n=10; n<=100000000; n*=10)
{
printf("%28.16f\t %28.16f\n", zeta(4.0, n), zeta2(4.0, n));
}
printf("%s=%20.16f\n\n","PI^4/90", PI*PI*PI*PI/90.0);
for (long long int n=10; n<=10000000000; n*=10)
{
printf("%28.16f\t %28.16f\n", zeta(2.0, n), zeta2(2.0, n));
}
printf("%s=%20.16f\n","PI^2/6 ", PI*PI/6.0);
}
you get
1.0820365834937564 1.0820365834937566
1.0823229053444732 1.0823229053444725
1.0823232333783044 1.0823232333783073
1.0823232337108049 1.0823232337108359
1.0823232337111379 1.0823232337109849
1.0823232337111381 1.0823232337109849
1.0823232337111381 1.0823232337109849
1.0823232337111381 1.0823232337109849
PI^4/90= 1.0823232337111379
1.5497677311665408 1.5497677311665408
1.6349839001848929 1.6349839001848925
1.6439345666815597 1.6439345666815606
1.6448340718480596 1.6448340718480665
1.6449240668982261 1.6449240668982523
1.6449330668487265 1.6449330668487985
1.6449339668482315 1.6449339668477756
1.6449340568482265 1.6449340573291047
1.6449340658482263 1.6449340600880324
1.6449340667482264 1.6449340600880324
PI^2/6 = 1.6449340668482264
see how the convergence of zeta_simple stops after a while... For convergence to continue you have to use zeta
You can also see that for 10000000000 operations (hence the use of long long int) you only get a precision on 9 digits for s=2. And as s increase so does the rate of convergence.
Therefore for small s to be efficient people use accelerated convergence formulae.
If you want to dig further I recommend you look at https://math.stackexchange.com/questions/183680/modern-formula-for-calculating-riemann-zeta-function
Also wat is really interesting is when you start poking around with s complex

Why am i not able to print 47th fibonacci number correctly?

I am using 64 bit operating system ,then also i am not able to print 46th fibonacci number correctly which is less than 4 billion.
#include<cs50.h>
#include<stdio.h>
int main(void)
{
unsigned int n=50;
int array[n];
array[0]=0;
array[1]=1;
printf("%i\n",array[0]);
printf("%i\n",array[1]);
for(int i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%i\n",array[i]);
}
You have to use long long as your data type of the array. because You are going to store out-range numbers of the integer range.(-2,147,483,648 to 2,147,483,647)
And declaration of int i should be before the for loop.
#include<stdio.h>
int main(void)
{
int n=50;
long long array[n];
array[0]=0;
array[1]=1;
printf("%lli\n",array[0]);
printf("%lli\n",array[1]);
int i;
for(i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%lli\n",array[i]);
}
}
i am not able to print 46th fibonacci number correctly which is less than 4 billion.
You are most probably going out of range of an integer, which is from -4294967296 to 4294967295.
Change int array[n]; to long long array[n];
Also, the printf's should be changed from %i to %lli
Edit : On running the numbers, you get expected value of F(48) as 4807526976 which is out of range of an integer.
Using Rishikesh Raje's counting system (i.e. 1st Fibonacci is 1) where F(48) is 4807526976, then you weren't able to get F(47) 2971215073 because, as #kaylum commented, you used a signed integer array to hold your values which you need to change to unsigned, and well as change your printf statement to print an unsigned. This would allow you to reach the limit of 32 bit arithmetic:
#include <stdio.h>
#define LIMIT (50)
int main(void) {
unsigned int array[LIMIT] = {0, 1};
printf("%u\n", array[0]);
printf("%u\n", array[1]);
for (size_t i = 2; i < LIMIT; i++)
{
array[i] = array[i - 1] + array[i - 2];
printf("%u\n", array[i]);
}
return 0;
}
To get beyond 32 bits, you can switch to long, or long longs as Rishikesh Raje suggests, but work with unsigned variants if you want to reach the maximum result you can with a given number of bits.
Either Use an unsigned integer array or for more higher values use unsigned long long long array but you don't need an array to print fibonacci series you can simply do this:-
void main()
{
unsigned long long i=1, num1=1, num2=0;
printf("1 \n");
for(i; i<100 ; i++)
{
num1=num1+num2;
num2=num1-num2;
printf("%lli \n", num1);
}
getch();
}

Time limit exceeded error on spoj.. How can i improve my solution?

We are given an array a[1..N]. For each element a[i] in the array, we note down the sum of all the elements which are smaller and occur before the present element. I need to calculate the total sum for every element in the array.
Constraints:
1<=N<=10^5
All elements will be between 0 and 10^6.
Here is the link to my question: http://www.spoj.com/problems/DCEPC206/. I'm using the approach shown below, but I'm getting TIME LIMIT EXCEEDED error on SPOJ. How can I improve my solution?
include
int main()
{
long n,a[100000],i,j,sum;
printf("enter the number of elements");
scanf("%ld",&n);
printf("enter the elements of the array");
for(i=0;i<n;i++)
scanf("%ld",&a[i]);
sum=0;
for(i=1;i<n;i++)
for(j=i-1;j>=0;j--)
if(a[i]>a[j])
sum+=a[j];
printf("\n%ld",sum);
return 0;
}
Yours is a trivial implementation which takes time of the order of O(n^2) but for the solution to get accepted you have to use Divide and Conquer as you do in Merge Sort which takes only O(NLogN) time compared to simpler sorting algorithms like Bubble Sort,etc.
For this you simply can change the Mergesort implementation a little bit simply by adding 2-3 lines of code in it. For understanding this better go through question of counting inversions in an array.(http://www.geeksforgeeks.org/counting-inversions/) Then you will realize you simply have to consider pairs opposite in nature to inversion and add all the smaller elements of all such pairs . For example - in an array 1,4,2,5 consider 4,2 is inversion but we have to consider pairs like 2,5 and 1,2 to get the solution. In every such pair keep adding the left no. ( Think hard about how it is doing our job !! )
For your reference go thoroughly through this merge sort code in which i have small changes to get a correct accepted solution.(sum variable stores the resultant value)
#include <stdio.h>
#include <stdlib.h>
long long int sum;
void merge(long long int c[],long long int arr[],long long int start,long long int middle,long long int end)
{
long long int i=0,j=start,k=middle;
while((j<middle)&&(k<end))
{
if(arr[j]<arr[k])
{
sum=sum+((end-k)*arr[j]);
c[i]=arr[j];
i++;j++;
}
else
{
c[i]=arr[k];
i++;k++;
}
}
while(j<middle)
{
c[i]=arr[j];
i++;
j++;
}
while(k<end)
{
c[i]=arr[k];
i++;
k++;
}
}
void msort(long long int arr[],long long int start,long long int end)
{
long long int middle=(start+end)/2;
if((end-start)==1)
{ return ;
}
msort(arr,start,middle);
msort(arr,middle,end);
long long int *c;
c=(long long int*)malloc(sizeof(long long int)*(end-start));
merge(c,arr,start,middle,end);
long long int i,j=0;
for(i=start;i<end;i++)
{
arr[i]=c[j];
j++;
}
}
void swap (long long int x[],long long int m,long long int n)
{
long long int t= x[m];
x[m]=x[n];
x[n]=t;
}
int main()
{
int t,i;
long long int n,*arr,j;
scanf("%d",&t);
for(i=0;i<t;i++)
{
scanf("%lld",&n);
arr = ( long long int * ) malloc ( sizeof(long long int) * n + 10);
for(j=0;j<n;j++)
{
scanf("%lld",&arr[j]);
}
sum=0;
msort(arr,0,n);
// for(j=0;j<n;j++)
// printf("%lld ",arr[j]);
printf("%lld\n",sum);
}
return 0;
}

Resources