Task: Pathological floating point problems

C: #include<stdio.h>
#include<gmp.h>

void firstCase(){
	mpf_t a,b,c;
	
	mpf_inits(a,b,c,NULL);
	
	mpf_set_str(a,"0.1",10);
	mpf_set_str(b,"0.2",10);
	mpf_add(c,a,b);
	
	gmp_printf("\n0.1 + 0.2 = %.*Ff",20,c);
}

void pathologicalSeries(){
	int n;
	mpf_t v1, v2, vn, a1, a2, a3, t2, t3, prod;
	
	mpf_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);
	
	mpf_set_str(v1,"2",10);
	mpf_set_str(v2,"-4",10);
	mpf_set_str(a1,"111",10);
	mpf_set_str(a2,"1130",10);
	mpf_set_str(a3,"3000",10);
	
	for(n=3;n<=100;n++){
		mpf_div(t2,a2,v2);
		mpf_mul(prod,v1,v2);
		mpf_div(t3,a3,prod);
		mpf_add(vn,a1,t3);
		mpf_sub(vn,vn,t2);
		
		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,vn);
		}
		
		mpf_set(v1,v2);
		mpf_set(v2,vn);
	}
}

void healthySeries(){
	int n;
	
	mpf_t num,denom,result;
	mpq_t v1, v2, vn, a1, a2, a3, t2, t3, prod;
	
	mpf_inits(num,denom,result,NULL);
	mpq_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);
	
	mpq_set_str(v1,"2",10);
	mpq_set_str(v2,"-4",10);
	mpq_set_str(a1,"111",10);
	mpq_set_str(a2,"1130",10);
	mpq_set_str(a3,"3000",10);
	
	for(n=3;n<=100;n++){
		mpq_div(t2,a2,v2);
		mpq_mul(prod,v1,v2);
		mpq_div(t3,a3,prod);
		mpq_add(vn,a1,t3);
		mpq_sub(vn,vn,t2);
		
		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			mpf_set_z(num,mpq_numref(vn));
			mpf_set_z(denom,mpq_denref(vn));
			mpf_div(result,num,denom);

			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,result);
		}
		
		mpq_set(v1,v2);
		mpq_set(v2,vn);
	}
}

int main()
{	
	mpz_t rangeProd;
	
	firstCase();
	
	printf("\n\nPathological Series : ");
	
	pathologicalSeries();
	
	printf("\n\nNow a bit healthier : ");
	
	healthySeries();

	return 0;
}










Fortran:       SUBROUTINE MULLER
       REAL*4 VN,VNL1,VNL2	
       REAL*8 WN,WNL1,WNL2	
       INTEGER I		
        WRITE (6,1)		
    1   FORMAT ("Muller's sequence should converge to six...",/
     1   "  N     Single      Double")
        VNL1 = 2; VN = -4	
        WNL1 = 2; WN = -4	
        DO I = 3,36			
          VNL2 = VNL1; VNL1 = VN		
          WNL2 = WNL1; WNL1 = WN		
          VN = 111 - 1130/VNL1 + 3000/(VNL1*VNL2)	
          WN = 111 - 1130/WNL1 + 3000/(WNL1*WNL2)	
          WRITE (6,2) I,VN,WN			
    2     FORMAT (I3,F12.7,F21.16)		
        END DO				
      END SUBROUTINE MULLER	

      SUBROUTINE CBS		
       INTEGER YEAR	
       REAL*4 V		
       REAL*8 W		
        V = 1; W = 1		
        V = EXP(V) - 1		
        W = EXP(W) - 1		
        WRITE (6,1)		
    1   FORMAT (///"The Chaotic Bank Society in action..."/"Year")
        WRITE (6,2) 0,V,W	
    2   FORMAT (I3,F16.7,F28.16)
        DO YEAR = 1,25		
          V = V*YEAR - 1	
          W = W*YEAR - 1	
          WRITE (6,2) YEAR,V,W	
        END DO			
      END SUBROUTINE CBS	

      REAL*4 FUNCTION SR4(A,B)	
       REAL*4 A,B
        SR4 = 333.75*B**6
     1      + A**2*(11*A**2*B**2 - B**6 - 121*B**4 - 2)
     2      + 5.5*B**8 + A/(2*B)
      END FUNCTION SR4
      REAL*8 FUNCTION SR8(A,B)	
       REAL*8 A,B
        SR8 = 333.75*B**6	
     1      + A**2*(11*A**2*B**2 - B**6 - 121*B**4 - 2)
     2      + 5.5*B**8 + A/(2*B)
      END FUNCTION SR8

      PROGRAM POKE
      REAL*4 V	
      REAL*8 W	
      WRITE (6,1) RADIX(V),DIGITS(V),"single",DIGITS(W),"double"
    1   FORMAT ("Floating-point arithmetic is conducted in base ",I0,/
     1   2(I3," digits for ",A," precision",/))
      WRITE (6,*) "Single precision limit",HUGE(V)
      WRITE (6,*) "Double precision limit",HUGE(W)
      WRITE (6,*)

      CALL MULLER

      CALL CBS

      WRITE (6,10)
   10 FORMAT (///"Evaluation of Siegfried Rump's function of 1988",
     1 " where F(77617,33096) = -0.827396059946821")
      WRITE (6,*) "Single precision:",SR4(77617.0,33096.0)
      WRITE (6,*) "Double precision:",SR8(77617.0D0,33096.0D0)	
      END