Rev 7038 | Rev 7111 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7038 | Rev 7076 | ||
---|---|---|---|
Line 2... | Line 2... | ||
2 | 2 | ||
3 | ********************************************************************************* |
3 | ********************************************************************************* |
4 | * J.M. Evers 3/2012 * |
4 | * J.M. Evers 3/2012 * |
5 | * This is all amateur scriblings... So no copyrights. * |
5 | * This is all amateur scriblings... So no copyrights. * |
6 | * This source code file, and compiled objects derived from it, |
6 | * This source code file, and compiled objects derived from it, * |
7 | * can be used and distributed without restriction, including for commercial use * |
7 | * can be used and distributed without restriction, including for commercial use * |
8 | * No warrenty whatsoever |
8 | * No warrenty whatsoever * |
9 | ********************************************************************************* |
9 | ********************************************************************************* |
10 | 20/6/2012 |
10 | 20/6/2012 |
11 | Corrected significance flaw when using prefixes |
11 | Corrected significance flaw when using prefixes |
12 | Simplified routines |
12 | Simplified routines |
13 | Added type = 5 : prefix-notation with words (nano,mega,giga...etc) |
13 | Added type = 5 : prefix-notation with words (nano,mega,giga...etc) |
Line 41... | Line 41... | ||
41 | default : calc notation : 120000,3 -> 1.20*10^5 |
41 | default : calc notation : 120000,3 -> 1.20*10^5 |
42 | type = 0 : calc notation : 120000,3,0 -> 1.20*10^5 |
42 | type = 0 : calc notation : 120000,3,0 -> 1.20*10^5 |
43 | type = 1 : html notation : 120000,3,1 -> 1.20×10<sup>5</sup> |
43 | type = 1 : html notation : 120000,3,1 -> 1.20×10<sup>5</sup> |
44 | type = 2 : latex notation : 120000,3,2 -> 1.20 \times 10^{5} |
44 | type = 2 : latex notation : 120000,3,2 -> 1.20 \times 10^{5} |
45 | type = 3 : prefix-notation : 120000,3,3 -> 120.0 k |
45 | type = 3 : prefix-notation : 120000,3,3 -> 120.0 k |
46 | type = 3 : if -24 > prefix > 24 -> type = 1 (html) |
46 | type = 3 : if -24 > prefix > 24 -> type = 1 (html) |
47 | type = 4 : mathml notation |
47 | type = 4 : mathml notation |
48 | 48 | ||
49 | multiple conversion: use space between arguments |
49 | multiple conversion: use space between arguments |
50 | scienceprint 120000,4 122900,5 120036,6,3 --> 120.0*10^3,122.90*10^3,120.036 k |
50 | scienceprint 120000,4 122900,5 120036,6,3 --> 120.0*10^3,122.90*10^3,120.036 k |
51 | 51 | ||
52 | 24 yotta Y |
52 | 24 yotta Y |
53 | 21 zetta Z |
53 | 21 zetta Z |
54 | 18 exa E |
54 | 18 exa E |
55 | 15 peta |
55 | 15 peta P |
56 | 12 tera T |
56 | 12 tera T |
57 | 9 giga G |
57 | 9 giga G |
58 | 6 mega M |
58 | 6 mega M |
59 | 3 kilo k |
59 | 3 kilo k |
60 | 60 | ||
61 | 2 hecto h |
61 | 2 hecto h |
62 | 1 deca da |
62 | 1 deca da |
63 | -1 deci d |
63 | -1 deci d |
64 | -2 centi c |
64 | -2 centi c |
65 | 65 | ||
66 | -3 milli m |
66 | -3 milli m |
67 | -6 micro µ |
67 | -6 micro µ |
68 | -9 nano n |
68 | -9 nano n |
69 | -12 pico p |
69 | -12 pico p |
70 | -15 femto f |
70 | -15 femto f |
71 | -18 atto a |
71 | -18 atto a |
72 | -21 zepto z |
72 | -21 zepto z |
73 | -24 yocto y |
73 | -24 yocto y |
74 | 74 | ||
75 | */ |
75 | */ |
76 | 76 | ||
77 | #include <stdio.h> |
77 | #include <stdio.h> |
78 | #include <math.h> |
78 | #include <math.h> |
Line 93... | Line 93... | ||
93 | /* if either sub_word or rep_word is NULL, duplicate word a let caller handle it */ |
93 | /* if either sub_word or rep_word is NULL, duplicate word a let caller handle it */ |
94 | if ( sub_word == NULL || rep_word == NULL ) return strdup(word); |
94 | if ( sub_word == NULL || rep_word == NULL ) return strdup(word); |
95 | new_word = strdup (word); |
95 | new_word = strdup (word); |
96 | head = new_word; |
96 | head = new_word; |
97 | while ( (part_word = strstr ( head, sub_word ))){ |
97 | while ( (part_word = strstr ( head, sub_word ))){ |
98 | old_word = new_word; |
98 | old_word = new_word; |
99 | new_word = malloc ( strlen ( old_word ) - strlen ( sub_word ) + strlen ( rep_word ) + 1 ); |
99 | new_word = malloc ( strlen ( old_word ) - strlen ( sub_word ) + strlen ( rep_word ) + 1 ); |
100 | /*failed to alloc mem, free old word and return NULL */ |
100 | /*failed to alloc mem, free old word and return NULL */ |
101 | if ( new_word == NULL ){ |
101 | if ( new_word == NULL ){ |
102 | free (old_word);return NULL; |
102 | free (old_word);return NULL; |
103 | } |
103 | } |
Line 115... | Line 115... | ||
115 | char *printscience(double value, int sig, int format , int cnt ,int size){ |
115 | char *printscience(double value, int sig, int format , int cnt ,int size){ |
116 | static char *min[] = {"","m",MICRO,"n","p","f","a","z","y"}; |
116 | static char *min[] = {"","m",MICRO,"n","p","f","a","z","y"}; |
117 | static char *plus[] = {"","k", "M", "G", "T", "P", "E", "Z", "Y" }; |
117 | static char *plus[] = {"","k", "M", "G", "T", "P", "E", "Z", "Y" }; |
118 | static char *min_word[] = {"","milli","micro","nano","pico","femto","atto","zepto","yocto"}; |
118 | static char *min_word[] = {"","milli","micro","nano","pico","femto","atto","zepto","yocto"}; |
119 | static char *plus_word[] = {"","kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta" }; |
119 | static char *plus_word[] = {"","kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta" }; |
120 | char *sign = NULL;char *prefix = NULL; |
120 | char *sign = NULL;char *prefix = NULL;double pm;int factor; |
121 | int exponent10 = 0; |
121 | int exponent10 = 0; |
122 | int use_word = 0;if(format == 5){format = 3; use_word = 1;} /* switch to using words in stead of prefix */ |
122 | int use_word = 0;if(format == 5){format = 3; use_word = 1;} /* switch to using words in stead of prefix */ |
123 | if(value < 0.0) {pm = -0.5; sign = "-";value = -value;} else {sign = ""; pm = 0.5;} |
123 | if(value < 0.0) {pm = -0.5; sign = "-";value = -value;} else {sign = ""; pm = 0.5;} |
124 | if( sig == -1 ){ |
124 | if( sig == -1 ){ |
125 | /* |
125 | /* |
126 | no significance truncations...just science notation 1234 -> 1.234*10^3 |
126 | no significance truncations...just science notation 1234 -> 1.234*10^3 |
127 | try (!) to use same amount of digits |
127 | try (!) to use same amount of digits |
128 | */ |
128 | */ |
129 | sig = size; |
129 | sig = size; |
130 | if(format == 3){format = 1;} /* never prefix --> html notation */ |
130 | if(format == 3){format = 1;} /* never prefix --> html notation */ |
131 | } |
131 | } |
132 | if(value == 0){fprintf(stdout, "%s%.*f", sign, sig-1, value);return NULL;} /* no need to go further */ |
132 | if(value == 0){fprintf(stdout, "%s%.*f", sign, sig-1, value);return NULL;} /* no need to go further */ |
133 | if(value>1){ |
133 | if(value>1){ |
134 | while(value >= 10){ |
134 | while(value >= 10){ |
135 | value=value / 10.0; |
135 | value=value / 10.0; |
136 | exponent10++; |
136 | exponent10++; |
137 | /* need to set a limit to number of while loops ! */ |
137 | /* need to set a limit to number of while loops ! */ |
138 | if(exponent10 > 100){fprintf(stdout,"error : number too big (exponent > 100)\n");return 0;} |
138 | if(exponent10 > 100){fprintf(stdout,"error : number too big (exponent > 100)\n");return 0;} |
139 | } |
139 | } |
140 | } |
140 | } |
141 | else /* 0 < value < 1 --> exponent10 < 0 */ |
141 | else /* 0 < value < 1 --> exponent10 < 0 */ |
142 | { |
142 | { |
143 | while(value < 1){ |
143 | while(value < 1){ |
144 | value=value*10; |
144 | value=value*10; |
145 | exponent10--; |
145 | exponent10--; |
146 | /* need to set a limit to number of while loops ! */ |
146 | /* need to set a limit to number of while loops ! */ |
147 | if(exponent10 <-100){fprintf(stdout,"error : number too small (exponent < -100)\n");return 0;} |
147 | if(exponent10 <-100){fprintf(stdout,"error : number too small (exponent < -100)\n");return 0;} |
148 | } |
148 | } |
149 | } |
149 | } |
150 | /* 27/9/2013 avoid truncating and do rounding...but not with 7 significant digits*/ |
150 | /* 27/9/2013 avoid truncating and do rounding...but not with 7 significant digits*/ |
151 | if(sig > 6){factor = 100000;}else{factor = pow(10,sig+1);} |
151 | if(sig > 6){factor = 100000;}else{factor = pow(10,sig+1);} |
152 | value = (round(factor*value + (pm) ))/factor; /* pm = +/- 0.5 */ |
152 | value = (round(factor*value + (pm) ))/factor; /* pm = +/- 0.5 */ |
153 | if(format == 3 && ((exponent10 < PREFIX_START) || (exponent10 > PREFIX_END))){ |
153 | if(format == 3 && ((exponent10 < PREFIX_START) || (exponent10 > PREFIX_END))){ |
154 | format = 1; /* not in my list of prefixes ; print in html ! */ |
154 | format = 1; /* not in my list of prefixes ; print in html ! */ |
155 | } |
155 | } |
156 | sig = sig - 1; /* "%.*f" counts the "." */ |
156 | sig = sig - 1; /* "%.*f" counts the "." */ |
157 | if(cnt > 1){fprintf(stdout,",");}/* more than one conversion to do : make list */ |
157 | if(cnt > 1){fprintf(stdout,",");}/* more than one conversion to do : make list */ |
158 | int idx=0;int exp=0; |
158 | int idx=0;int exp=0; |
159 | if(exponent10 == 0){format = 6;} /* no need for 2*10^0 */ |
159 | if(exponent10 == 0){format = 6;} /* no need for 2*10^0 */ |
160 | if(sig < 0){sig = 0;} /* better be safe than sorry... */ |
160 | if(sig < 0){sig = 0;} /* better be safe than sorry... */ |
161 | switch(format){ |
161 | switch(format){ |
162 | case 0: fprintf(stdout, "%s%.*f*10^%d", sign, sig, value, exponent10);break; |
162 | case 0: fprintf(stdout, "%s%.*f*10^%d", sign, sig, value, exponent10);break; |
163 | case 1: fprintf(stdout, "%s%.*f×10<sup>%d</sup>", sign, sig, value, exponent10);break; |
163 | case 1: fprintf(stdout, "%s%.*f×10<sup>%d</sup>", sign, sig, value, exponent10);break; |
164 | case 2: fprintf(stdout, "%s%.*f \\times 10^{%d}", sign, sig, value, exponent10);break; |
164 | case 2: fprintf(stdout, "%s%.*f \\times 10^{%d}", sign, sig, value, exponent10);break; |
165 | case 3: |
165 | case 3: |
166 | /* |
166 | /* |
167 | 1,1,3 -> 1 |
167 | 1,1,3 -> 1 |
168 | 10,1,3 -> 1*10^-2 k |
168 | 10,1,3 -> 1*10^-2 k |
169 | 100,1,3 -> 1*10^-1 k |
169 | 100,1,3 -> 1*10^-1 k |
170 | 1000,1,3 -> 1 k |
170 | 1000,1,3 -> 1 k |
Line 183... | Line 183... | ||
183 | 0.000001,1,3 -> 1 µ |
183 | 0.000001,1,3 -> 1 µ |
184 | 0.0000001,1,3-> 1*10^-1 µ |
184 | 0.0000001,1,3-> 1*10^-1 µ |
185 | 0.00000001,1,3-> 1*10^-2 µ |
185 | 0.00000001,1,3-> 1*10^-2 µ |
186 | 0.000000001,1,3-> 1 n |
186 | 0.000000001,1,3-> 1 n |
187 | */ |
187 | */ |
188 | exp = exponent10%3; |
188 | exp = exponent10%3; |
189 | idx = round(exponent10/3); |
189 | idx = round(exponent10/3); |
190 | if( exponent10 > 0 ){ |
190 | if( exponent10 > 0 ){ |
191 | if(use_word == 0 ){ prefix = plus[idx]; } else { prefix = plus_word[idx]; } |
191 | if(use_word == 0 ){ prefix = plus[idx]; } else { prefix = plus_word[idx]; } |
192 | } |
192 | } |
193 | else |
193 | else |
194 | { |
194 | { |
195 | if(use_word == 0){ prefix = min[-1*idx]; } else { prefix = min_word[-1*idx]; } |
195 | if(use_word == 0){ prefix = min[-1*idx]; } else { prefix = min_word[-1*idx]; } |
196 | } |
196 | } |
197 | if( exp == 0){ |
197 | if( exp == 0){ |
198 | fprintf(stdout, "%s%.*f %s",sign, sig, value,prefix); |
198 | fprintf(stdout, "%s%.*f %s",sign, sig, value,prefix); |
199 | } |
199 | } |
200 | else |
200 | else |
201 | { |
201 | { |
202 | fprintf(stdout, "%s%.*f×10<sup>%d</sup> %s", sign, sig, value, exp, prefix); |
202 | fprintf(stdout, "%s%.*f×10<sup>%d</sup> %s", sign, sig, value, exp, prefix); |
203 | } |
203 | } |
204 | break; |
204 | break; |
205 | case 4: fprintf(stdout, "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"inline\"><mstyle id=\"wims_mathml\" mathsize=\"110%%\"><mn>%s%.*f</mn><mo>×</mo><msup><mn>10</mn><mn>%d</mn></msup></mstyle></math>", sign, sig, value, exponent10);break; |
205 | case 4: fprintf(stdout, "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"inline\"><mstyle id=\"wims_mathml\" mathsize=\"110%%\"><mn>%s%.*f</mn><mo>×</mo><msup><mn>10</mn><mn>%d</mn></msup></mstyle></math>", sign, sig, value, exponent10);break; |
206 | case 5: break; |
206 | case 5: break; |
207 | case 6: fprintf(stdout, "%s%.*f",sign,sig,value);break; |
207 | case 6: fprintf(stdout, "%s%.*f",sign,sig,value);break; |
208 | default: break; |
208 | default: break; |
209 | } |
209 | } |
210 | return NULL; |
210 | return NULL; |
211 | } |
211 | } |
212 | 212 | ||
213 | int main( int argc , char *argv[]){ |
213 | int main( int argc , char *argv[]){ |
214 | 214 | ||
215 | if( argc < 2){ |
215 | if( argc < 2){ |
216 | fprintf(stdout,"syntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n"); |
216 | fprintf(stdout,"syntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n"); |
217 | return 0; |
217 | return 0; |
218 | } |
218 | } |
219 | 219 | ||
220 | double number = 0; |
220 | double number = 0; |
221 | int significance = 0,type = 0,idx = 0,cnt = 1,size = 0; |
221 | int significance = 0,type = 0,idx = 0,cnt = 1,size = 0; |
222 | char *input = "\0",*ptr = "\0"; |
222 | char *input = "\0",*ptr = "\0"; |
Line 226... | Line 226... | ||
226 | /* Ee +- are allowed : 12.34e+05 12.34e-08 */ |
226 | /* Ee +- are allowed : 12.34e+05 12.34e-08 */ |
227 | 227 | ||
228 | /* walk through argument 1 to end, and call function scienceprint(a,b,c) */ |
228 | /* walk through argument 1 to end, and call function scienceprint(a,b,c) */ |
229 | input = argv[cnt]; |
229 | input = argv[cnt]; |
230 | while( input != NULL ){ |
230 | while( input != NULL ){ |
231 | if(cnt > MAX_CONV){fprintf(stdout,"\nerror: number of conversions exceeds limit of %d\n",MAX_CONV);return 0;} |
231 | if(cnt > MAX_CONV){fprintf(stdout,"\nerror: number of conversions exceeds limit of %d\n",MAX_CONV);return 0;} |
232 | while (*input){ /* loop through invalid chars. */ |
232 | while (*input){ /* loop through invalid chars. */ |
233 | if ( strchr(invalid_characters, *input) ){ |
233 | if ( strchr(invalid_characters, *input) ){ |
234 | fprintf(stdout,"\nerror : illegal character \"%s\" \n",input); |
234 | fprintf(stdout,"\nerror : illegal character \"%s\" \n",input); |
235 | return 0; |
235 | return 0; |
236 | } |
236 | } |
237 | input++; |
237 | input++; |
238 | } |
238 | } |
239 | /* reset input to actual value */ |
239 | /* reset input to actual value */ |
240 | input = argv[cnt]; |
240 | input = argv[cnt]; |
241 | ptr = (char *) strtok(input,","); |
241 | ptr = (char *) strtok(input,","); |
242 | idx = 0; |
242 | idx = 0; |
243 | type = 0; |
243 | type = 0; |
244 | size = 0; |
244 | size = 0; |
245 | while( ptr != NULL ){ |
245 | while( ptr != NULL ){ |
246 | switch( idx ){ |
246 | switch( idx ){ |
247 | case 0: |
247 | case 0: |
248 | /* size only interesting when 'significance=-1' |
248 | /* size only interesting when 'significance=-1' |
249 | determine number of digits : 1.23445e+23 -> size = 6 |
249 | determine number of digits : 1.23445e+23 -> size = 6 |
250 | */ |
250 | */ |
251 | size = strlen(ptr); |
251 | size = strlen(ptr); |
252 | if( strstr(ptr,".") != NULL){size = size - 1 ;} |
252 | if( strstr(ptr,".") != NULL){size = size - 1 ;} |
253 | if( strstr(ptr,"*10^") != NULL){ |
253 | if( strstr(ptr,"*10^") != NULL){ |
254 | ptr = str_replace(ptr,"*10^","E"); |
254 | ptr = str_replace(ptr,"*10^","E"); |
255 | if(ptr == NULL){ |
255 | if(ptr == NULL){ |
256 | fprintf(stdout,"error : in replacement of 10^ notation\n"); |
256 | fprintf(stdout,"error : in replacement of 10^ notation\n"); |
257 | return 0; |
257 | return 0; |
258 | } |
258 | } |
259 | size = size - 3; |
259 | size = size - 3; |
260 | } |
260 | } |
261 | if( strstr(ptr,"E") != NULL){size = size - strlen(strstr(ptr,"E"));} |
261 | if( strstr(ptr,"E") != NULL){size = size - strlen(strstr(ptr,"E"));} |
262 | if( strstr(ptr,"e") != NULL){size = size - strlen(strstr(ptr,"e"));} |
262 | if( strstr(ptr,"e") != NULL){size = size - strlen(strstr(ptr,"e"));} |
263 | number = atof(ptr); |
263 | number = atof(ptr); |
264 | break; |
264 | break; |
265 | case 1: significance = atoi(ptr); break; |
265 | case 1: significance = atoi(ptr); break; |
266 | case 2: type = atoi(ptr); if(type < 0 || type > 5 ){type = 0;} break; |
266 | case 2: type = atoi(ptr); if(type < 0 || type > 5 ){type = 0;} break; |
267 | default: break; |
267 | default: break; |
268 | } |
268 | } |
269 | idx++; |
269 | idx++; |
270 | ptr = (char *) strtok(NULL,","); |
270 | ptr = (char *) strtok(NULL,","); |
271 | } |
271 | } |
272 | /* number and precision are mandatory: default type=0 */ |
272 | /* number and precision are mandatory: default type=0 */ |
273 | if( idx < 2 || idx > 3){fprintf(stdout,"\nsyntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n");return 0;} |
273 | if( idx < 2 || idx > 3){fprintf(stdout,"\nsyntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n");return 0;} |
274 | /* call conversion routine */ |
274 | /* call conversion routine */ |
275 | printscience(number, significance, type , cnt , size); |
275 | printscience(number, significance, type , cnt , size); |
276 | cnt++; |
276 | cnt++; |
277 | input = argv[cnt]; |
277 | input = argv[cnt]; |
278 | } |
278 | } |
279 | fprintf(stdout,"\n"); |
279 | fprintf(stdout,"\n"); |
280 | return 0; |
280 | return 0; |
281 | } |
281 | } |
282 | 282 |