Rev 5801 | Rev 5950 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5171 | schaersvoo | 1 | /* |
5177 | schaersvoo | 2 | |
5171 | schaersvoo | 3 | ********************************************************************************* |
5177 | schaersvoo | 4 | * J.M. Evers 3/2012 * |
5 | * This is all amateur scriblings... So no copyrights. * |
||
6 | * This source code file, and compiled objects derived from it, * |
||
7 | * can be used and distributed without restriction, including for commercial use * |
||
5196 | schaersvoo | 8 | * No warrenty whatsoever * |
5171 | schaersvoo | 9 | ********************************************************************************* |
5196 | schaersvoo | 10 | |
5801 | schaersvoo | 11 | 18/10/2012 : |
12 | Added Mathml output |
||
13 | Added option significance=-1 |
||
14 | To be used when there is no significance known ; just tries to print the number in science notation |
||
5840 | schaersvoo | 15 | Using the original amount of digits used in "number" argument |
16 | !exec scienceprint 123.445000e+23,-1 --> 1.23445000*10^25 |
||
5801 | schaersvoo | 17 | |
18 | ********************************************************************************* |
||
19 | |||
5177 | schaersvoo | 20 | WIMS usage: |
21 | sci_num = !exec scienceprint number,significance,type |
||
5196 | schaersvoo | 22 | |
5171 | schaersvoo | 23 | number: a number |
5196 | schaersvoo | 24 | significance : desired precision |
5801 | schaersvoo | 25 | type (optional args): calc = 0 / html = 1 / latex = 2 / prefix = 3 / mathml = 4 |
5177 | schaersvoo | 26 | |
5196 | schaersvoo | 27 | default : calc notation : 120000,3 -> 1.20*10^5 |
28 | type = 0 : calc notation : 120000,3,0 -> 1.20*10^5 |
||
29 | type = 1 : html notation : 120000,3,1 -> 1.20×10<sup>5</sup> |
||
30 | type = 2 : latex notation : 120000,3,2 -> 1.20 \times 10^{5} |
||
5171 | schaersvoo | 31 | type = 3 : prefix-notation : 120000,3,3 -> 120.0 k |
5196 | schaersvoo | 32 | type = 3 : if -24 > prefix > 24 -> type = 1 (html) |
5801 | schaersvoo | 33 | type = 4 : mathml notation |
5171 | schaersvoo | 34 | |
35 | multiple conversion: use space between arguments |
||
5177 | schaersvoo | 36 | scienceprint 120000,4 122900,5 120036,6,3 --> 120.0*10^3,122.90*10^3,120.036 k |
5171 | schaersvoo | 37 | |
5196 | schaersvoo | 38 | 24 yotta Y |
39 | 21 zetta Z |
||
40 | 18 exa E |
||
41 | 15 peta P |
||
42 | 12 tera T |
||
43 | 9 giga G |
||
44 | 6 mega M |
||
45 | 3 kilo k |
||
46 | 2 hecto h |
||
47 | 1 deca da |
||
48 | -1 deci d |
||
49 | -2 centi c |
||
50 | -3 milli m |
||
51 | -6 micro µ |
||
52 | -9 nano n |
||
53 | -12 pico p |
||
54 | -15 femto f |
||
55 | -18 atto a |
||
56 | -21 zepto z |
||
57 | -24 yocto y |
||
58 | |||
5171 | schaersvoo | 59 | */ |
60 | |||
61 | #include <stdio.h> |
||
62 | #include <math.h> |
||
63 | #include <string.h> |
||
64 | #include <stdlib.h> |
||
65 | #define MICRO "µ" |
||
66 | #define PREFIX_START (-24) |
||
5196 | schaersvoo | 67 | #define PREFIX_END 24 |
68 | #define MAX_CONV 256 |
||
5171 | schaersvoo | 69 | |
5801 | schaersvoo | 70 | char *printscience(double value, int sig, int format , int cnt ,int size){ |
5196 | schaersvoo | 71 | static char *prefix[] = { "y", "z", "a", "f", "p", "n", MICRO, "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" }; |
5177 | schaersvoo | 72 | double display, fract; |
73 | char *sign = NULL; |
||
74 | int exponent10; |
||
5801 | schaersvoo | 75 | if( sig == -1 ){ |
76 | /* no significance truncations...just science notation 1234 -> 1.234*10^3 ; try (!) to use same amount of digits*/ |
||
77 | sig = size; |
||
78 | if(format == 3){format = 1;} /* no prefix --> html noation */ |
||
79 | if(value < 0.0) {sign = "-";value = -value;sig--;} else {sign = "";} |
||
80 | exponent10=0; |
||
81 | if(value>=1){ |
||
82 | while(value > 10){ |
||
83 | value=value / 10.0; |
||
84 | exponent10++; |
||
5840 | schaersvoo | 85 | /* need to set a limit to number of while loops ! */ |
86 | if(exponent10 > 100){fprintf(stdout,"error : number too big (exponent > 100)\n");return 0;} |
||
5196 | schaersvoo | 87 | } |
88 | } |
||
5801 | schaersvoo | 89 | else /* 0 < value < 1 --> exponent10 < 0 */ |
90 | { |
||
91 | while(value < 1){ |
||
92 | value=value*10; |
||
93 | exponent10--; |
||
5840 | schaersvoo | 94 | /* need to set a limit to number of while loops ! */ |
95 | if(exponent10 <-100){fprintf(stdout,"error : number too small (exponent < -100)\n");return 0;} |
||
5801 | schaersvoo | 96 | } |
97 | } |
||
5177 | schaersvoo | 98 | } |
5801 | schaersvoo | 99 | else |
5177 | schaersvoo | 100 | { |
5801 | schaersvoo | 101 | if(value < 0.0) {sign = "-";value = -value;} else {sign = "";} |
102 | exponent10 = lrint( floor( log10(value) ) );/* correctly round to desired precision */ |
||
103 | value *= pow(10.0, sig - 1 - exponent10); |
||
104 | fract = modf(value, &display); |
||
105 | if(fract >= 0.5){display += 1.0;} |
||
106 | value = display * pow(10.0, exponent10 - sig + 1); |
||
107 | if(exponent10 > 0){exponent10 = (exponent10/3)*3;}else{exponent10 = ((-exponent10+3)/3)*(-3);} |
||
108 | value *= pow(10.0, -exponent10); |
||
109 | if(format != 3){ /* allow all powers; not limited by prefix list */ |
||
110 | if(value > 10.0){ |
||
111 | while(value >= 10){ |
||
112 | value = value / 10.0; |
||
113 | exponent10++; |
||
5840 | schaersvoo | 114 | /* need to set a limit to number of while loops ! */ |
115 | if(exponent10 > 100){fprintf(stdout,"error : number too big (exponent > 100)\n");return 0;} |
||
5801 | schaersvoo | 116 | } |
117 | } |
||
5171 | schaersvoo | 118 | } |
5801 | schaersvoo | 119 | else /* steps of powers dividable by 3 used for prefix notation */ |
5171 | schaersvoo | 120 | { |
5801 | schaersvoo | 121 | if (value >= 1000.0) { |
122 | value = value / 1000.0; |
||
123 | exponent10 = exponent10 + 3; |
||
5177 | schaersvoo | 124 | } |
5196 | schaersvoo | 125 | else |
126 | { |
||
5801 | schaersvoo | 127 | if(value >= 100.0){ |
128 | sig = sig - 2; |
||
5196 | schaersvoo | 129 | } |
5801 | schaersvoo | 130 | else |
131 | { |
||
132 | if(value >= 10.0){ |
||
133 | sig = sig - 1; |
||
134 | } |
||
135 | } |
||
5196 | schaersvoo | 136 | } |
5171 | schaersvoo | 137 | } |
5177 | schaersvoo | 138 | } |
139 | if(cnt > 1){fprintf(stdout,",");} |
||
5801 | schaersvoo | 140 | /* check on format style versus exponent */ |
5206 | schaersvoo | 141 | if(exponent10 == 0 ){ |
5801 | schaersvoo | 142 | format = 3; /* do not use 1.23*10^0 */ |
5196 | schaersvoo | 143 | } |
144 | else |
||
145 | { |
||
5206 | schaersvoo | 146 | if(exponent10 == 1){ |
5801 | schaersvoo | 147 | format = 3;/* do not use 1.23*10^1 */ |
5206 | schaersvoo | 148 | value = value * 10; |
149 | sig = sig - 1; |
||
5196 | schaersvoo | 150 | } |
5206 | schaersvoo | 151 | else |
152 | { |
||
153 | if(format == 3 && ((exponent10 < PREFIX_START) || (exponent10 > PREFIX_END))){ |
||
5801 | schaersvoo | 154 | format = 1; /* if no prefix available, revert to html presentation */ |
5206 | schaersvoo | 155 | } |
156 | } |
||
157 | |||
5196 | schaersvoo | 158 | } |
5283 | schaersvoo | 159 | if(sig < 1){sig = 1;} |
5196 | schaersvoo | 160 | if(format != 3 ){ |
5801 | schaersvoo | 161 | if( format == 0){ /* 'calculable' presentation */ |
5177 | schaersvoo | 162 | fprintf(stdout, "%s%.*f*10^%d", sign, sig-1, value, exponent10); |
5171 | schaersvoo | 163 | } |
164 | else |
||
165 | { |
||
5801 | schaersvoo | 166 | if( format == 1 ){ /* html presentation */ |
5177 | schaersvoo | 167 | fprintf(stdout, "%s%.*f×10<sup>%d</sup>", sign, sig-1, value, exponent10); |
5171 | schaersvoo | 168 | } |
5801 | schaersvoo | 169 | else |
5171 | schaersvoo | 170 | { |
5801 | schaersvoo | 171 | if(format == 2 ){/* latex presentation */ |
172 | fprintf(stdout, "%s%.*f \\times 10^{%d}", sign, sig-1, value, exponent10); |
||
173 | } |
||
174 | else |
||
175 | { /* mathml presentation */ |
||
176 | 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-1, value, exponent10); |
||
177 | } |
||
5171 | schaersvoo | 178 | } |
179 | } |
||
5801 | schaersvoo | 180 | } |
181 | else /* format = 3 : prefix presentation or other more suitable presentation */ |
||
5177 | schaersvoo | 182 | { |
183 | fprintf(stdout, "%s%.*f %s", sign, sig-1, value,prefix[(exponent10-PREFIX_START)/3]); |
||
5171 | schaersvoo | 184 | } |
5177 | schaersvoo | 185 | return NULL; |
186 | } |
||
187 | |||
188 | int main( int argc , char *argv[]){ |
||
5171 | schaersvoo | 189 | |
5177 | schaersvoo | 190 | if( argc < 2){ |
191 | fprintf(stdout,"syntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n"); |
||
192 | return 0; |
||
193 | } |
||
5801 | schaersvoo | 194 | |
5171 | schaersvoo | 195 | double number = 0; |
5801 | schaersvoo | 196 | int significance = 0,type = 0,idx = 0,cnt = 1,size = 0; |
5171 | schaersvoo | 197 | char *input = "\0",*ptr = "\0"; |
198 | |||
199 | /* test for illegal characters */ |
||
200 | const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz@#$%^*&()[]{};:~><?/\\|"; |
||
201 | /* Ee +- are allowed : 12.34e+05 12.34e-08 */ |
||
202 | |||
203 | /* walk through argument 1 to end, and call function scienceprint(a,b,c) */ |
||
204 | input = argv[cnt]; |
||
205 | while( input != NULL ){ |
||
5196 | schaersvoo | 206 | if(cnt > MAX_CONV){fprintf(stdout,"\nerror: number of conversions exceeds limit of %d\n",MAX_CONV);return 0;} |
5801 | schaersvoo | 207 | while (*input){ /* loop through invalid chars. */ |
5171 | schaersvoo | 208 | if ( strchr(invalid_characters, *input) ){ |
5801 | schaersvoo | 209 | fprintf(stdout,"\nerror : illegal character \"%s\" \n",input); |
5196 | schaersvoo | 210 | return 0; |
5171 | schaersvoo | 211 | } |
212 | input++; |
||
213 | } |
||
5801 | schaersvoo | 214 | /* reset input to actual value */ |
5171 | schaersvoo | 215 | input = argv[cnt]; |
216 | ptr = (char *) strtok(input,","); |
||
217 | idx = 0; |
||
218 | type = 0; |
||
5801 | schaersvoo | 219 | size = 0; |
5171 | schaersvoo | 220 | while( ptr != NULL ){ |
221 | switch( idx ){ |
||
5840 | schaersvoo | 222 | case 0: number = atof(ptr); |
223 | /* size only interesting when 'significance=-1' |
||
224 | determine number of digits : 1.23445e+23 -> size = 6 |
||
225 | */ |
||
226 | size = strlen(ptr);if( strstr(ptr,".") != NULL){ size = size - 1 ;} |
||
227 | if( strstr(ptr,"E") != NULL){size = size - strlen(strstr(ptr,"E"));} |
||
228 | if( strstr(ptr,"e") != NULL){size = size - strlen(strstr(ptr,"e"));} |
||
229 | break; |
||
5801 | schaersvoo | 230 | case 1: significance = atoi(ptr); break; |
231 | case 2: type = atoi(ptr); if(type < 0 || type > 4 ){type = 0;} break; |
||
5171 | schaersvoo | 232 | default: break; |
233 | } |
||
234 | idx++; |
||
235 | ptr = (char *) strtok(NULL,","); |
||
236 | } |
||
5801 | schaersvoo | 237 | /* number and precision are mandatory: default type=0 */ |
5196 | schaersvoo | 238 | if( idx < 2 || idx > 3){fprintf(stdout,"\nsyntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n");return 0;} |
5801 | schaersvoo | 239 | /* call conversion routine */ |
240 | printscience(number, significance, type , cnt , size); |
||
5171 | schaersvoo | 241 | cnt++; |
242 | input = argv[cnt]; |
||
243 | } |
||
244 | fprintf(stdout,"\n"); |
||
245 | return 0; |
||
246 | } |