Hatena::Groupcprogramming

C Study Diary

2008-12-11

c4ex2atof.cpp

16:44

Extend atof to handle scientific notation of the form 123.45e-6 where a floating-point number may be followed by e or E and an optionally signed exponent.

Question: if set ratio to float, the result is not accurate. Won't double*float be converted to double?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX 10

double atof(char* s){
	
	double number=0.0, ratio=1.0, ten=10.0;
	int i=0, non_num=0, point=-1, sign=1, psign=1, e=0, exp=0, digit=0;

	while(s[i]!='\0'){
		switch(s[i]){
			case ' ': non_num++; break;
			case '.': point=i; break;
			case '-': if(e) psign=-1; else {sign=-1; non_num++;} break;
			case '+': if(e) psign=1; else {sign=1; non_num++;} break;
			case 'e': e=1; break;
			case 'E': e=1; break;
			default: if(e) exp=exp*10+(s[i]-'0'); else { number=number*ten+(s[i]-'0'); digit++; }
		}
		i++;
	}
	/* negtive exp sign or exp =0 => ratio=0.1 ; positive exp sign => ratio = 10.0  */
	if(psign<0 || exp==0) ratio = 1/ten;
	else ratio = ten;
	
	/* if point appears */
	if(point!=-1){
		for(i=0;i<abs(psign*exp-(digit-(point-non_num)));i++)
			number = number * ratio; 
	}
	/* no point */	
	else {
		for(i=0;i<exp;i++)
			number = number * ratio; 
	}

	return number*sign;
	
}

int main(){
	
	char s1[]="-123e5";
	char s2[]="123.12E-5";	
	char s3[]="   123.E";
	char s4[]="   -.12312235";
	char s[MAX];
	printf("input a float number, eg, 123.11e+5\n");
	scanf("%s",&s);
	printf("%s->%.10g\n",s,atof(s));
	printf("Preset test numbers:\n");
	printf("%s->%.10g\n",s1,atof(s1));
	printf("%s->%.10g\n",s2,atof(s2));
	printf("%s->%.10g\n",s3,atof(s3));
	printf("%s->%.10g\n",s4,atof(s4)); 	
}	

Run:

$ ./c4ex2atof.exe
input a float number, eg, 123.11e+5
0e10
0e10->0
Preset test numbers:
-123e5->-12300000
123.12E-5->0.0012312
   123.E->123
   -.12312235->-0.12312235

zero_count.cpp

12:07

To count zeros in a certain range, say 1-100000.

Question: How to deal with number larger than 10^9? Is it a good idea to use double instead?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* direct count */
int zero_count(unsigned long s, unsigned long n)
{	
	int count=0;
	unsigned long i, t;

	for(i=s;i<=n;i++)
	{
		t=i;
		do{
			if(t%10==0) count++;
			
		}while((t=t/10)>0);			

	}
	return count;
}

/* f(n), count from 1 to n, not as flexible as the first function */
int zero_count_speedy(unsigned long n){

	int	count = 0, subcount=0;
	unsigned long begin, end;
	
	if(n==10) {
		count=1;
		return count;
	}else{	
	/* f(n) = f(n/10) + zero_num[(n/10+1)~2*n/10]*9+1 , eg, f(1000) = f(100) + zero_num[101-200]*9+1 */
		begin=n/10+1;
		end=2*n/10;
		subcount=zero_count(begin,end);
		count+=zero_count_speedy(n/10)+subcount*9+1;

	}
	return count;

}


int main(){
	unsigned long n, s;
	int count;
	clock_t sclock,eclock;
	
	printf("input range(<10^10):(eg, 1-1000)\n");
	scanf("%lu-%lu",&s,&n);
	printf("count zero in %lu-%lu\n",s,n);

	sclock=clock();
	count=zero_count(s,n);
	eclock=clock();
	printf("Total number of zeros within %d-%d: %d\nTime used: %fseconds\n", s, n, count, (double)(eclock-sclock)/CLOCKS_PER_SEC);	

	sclock=clock();
	count=zero_count_speedy(n);
	eclock=clock();
	printf("Total number of zeros within 1-%d: %d\nTime used: %fseconds\n", n, count, (double)(eclock-sclock)/CLOCKS_PER_SEC);	

	return 0;
	
}

Run:

$ ./zero_count.exe
input range(<10^10):(eg, 1-1000)
1-1000
count zero in 1-1000
Total number of zeros within 1-1000: 192
Time used: 0.000000seconds
Total number of zeros within 1-1000: 192
Time used: 0.000000seconds

$ ./zero_count.exe
input range(<10^10):(eg, 1-1000)
1-1000000000
count zero in 1-1000000000
Total number of zeros within 1-1000000000: 788888898
Time used: 68.297000seconds
Total number of zeros within 1-1000000000: 788888898
Time used: 7.438000seconds

lymanlyman2008/12/11 18:21for larger int, you can try unsigned long long int(search int64 or so, this might be different among platforms), which is 64 bit. for science calculate (to say, no precision limitation), c is not a good choice unless introduce external lib (if exists)

annancyannancy2008/12/11 18:34Thank you!!