Rev 5360 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5207 | schaersvoo | 1 | /* |
2 | ********************************************************************************* |
||
3 | * J.M. Evers 3/2012 * |
||
4 | * This is all amateur scriblings... So no copyrights. * |
||
5 | * This source code file, and compiled objects derived from it, * |
||
6 | * can be used and distributed without restriction, including for commercial use * |
||
7 | * No warrenty whatsoever * |
||
8 | ********************************************************************************* |
||
5213 | schaersvoo | 9 | syntax number_1 number2 number_3 ... number_n |
5207 | schaersvoo | 10 | |
5227 | schaersvoo | 11 | Treats a number as string array : no numerical evaluation ! |
12 | (pfffff...) |
||
5219 | schaersvoo | 13 | |
5213 | schaersvoo | 14 | example |
12133 | schaersvoo | 15 | shell : ./sigdigits "1.23" "1.230" "1.2300" "1.23e5" "1.23*10^5' "1.2300e5" ".12340000" "01.23*10^5" "1.2.3.4" |
16 | wims : !exec sigdigits 1.23 1.230 1.2300 1.23e5 1.23*10^5 1.2300e5 .12340000 01.23*10^5 1.2.3.4 |
||
5283 | schaersvoo | 17 | 3,1,2,1,0,1 |
18 | 4,1,3,1,0,1 |
||
19 | 5,1,4,1,0,1 |
||
20 | 3,1,2,10,5,1 |
||
21 | 3,1,2,10,5,1 |
||
22 | 5,1,4,10,5,1 |
||
12133 | schaersvoo | 23 | 8,1,8,1,0,1 |
5283 | schaersvoo | 24 | 3,2,2,10,5,0 |
25 | -1,-1,-1,-1,-1,-1 |
||
5207 | schaersvoo | 26 | |
5213 | schaersvoo | 27 | result is |
28 | 1 line per input number |
||
5283 | schaersvoo | 29 | 6 items per line: |
5207 | schaersvoo | 30 | |
5213 | schaersvoo | 31 | item 1) real number of significant digits in number_x (eg without leading zeros) |
5219 | schaersvoo | 32 | |
5283 | schaersvoo | 33 | item 2) number of digits left from decimal point or if no decimals: total number of digits (length) |
5207 | schaersvoo | 34 | |
5283 | schaersvoo | 35 | item 3) number of digits right from decimal point |
5207 | schaersvoo | 36 | |
5283 | schaersvoo | 37 | item 4) exponent base (if not present : 1) |
5207 | schaersvoo | 38 | |
5283 | schaersvoo | 39 | item 5) exponent (if not present : 0) |
5207 | schaersvoo | 40 | |
5283 | schaersvoo | 41 | item 6) indication : is the number correctly written ? 1 or 0 ( 000.1 is not correct...) |
5227 | schaersvoo | 42 | scientiffic: [1-9.*] *10^exp : 1.2345*10^5 is OK ... 12.345*10^4 or 0.12345*10^6 is "NOK" |
43 | a*10^b : 1 <= a <= 9 |
||
5219 | schaersvoo | 44 | |
45 | remarks: |
||
46 | - exponent: any other base will be tolerated : 4*7^5 base=7 exponent=5 -> 1,0,1,0,7,5,1 |
||
5283 | schaersvoo | 47 | - if number is 'nonsense' : -1,-1,-1,-1,-1 (1.23.4567 10^1.23.4 ; number will produce NaN in other math software) |
5219 | schaersvoo | 48 | |
49 | ruleset: |
||
50 | 120.2 : 4 significant digits |
||
5283 | schaersvoo | 51 | 120.2000 : 7 significant digits |
5356 | schaersvoo | 52 | 0.0000120 : 3 significant digits |
12133 | schaersvoo | 53 | .0000120 : 3 significant digits |
5219 | schaersvoo | 54 | scientiffic notation: |
5227 | schaersvoo | 55 | 1.202*10^5 : 4 significant digits |
56 | 1.20200*10^5 : 6 significant digits |
||
5219 | schaersvoo | 57 | |
5227 | schaersvoo | 58 | |
5213 | schaersvoo | 59 | */ |
5207 | schaersvoo | 60 | |
61 | #include <stdio.h> |
||
62 | #include <stdlib.h> |
||
63 | #include <string.h> |
||
64 | #define MAX_DIGITS 64 |
||
65 | #define MAX_CONV 64 |
||
66 | |||
5213 | schaersvoo | 67 | void append(char* s, char c){ |
68 | int len = strlen(s); |
||
69 | s[len] = c; |
||
70 | s[len+1] = '\0'; |
||
71 | } |
||
5207 | schaersvoo | 72 | |
73 | int main( int argc , char *argv[]){ |
||
74 | if( argc < 2){ |
||
75 | fprintf(stdout,"syntax error\n"); |
||
76 | exit(0); |
||
77 | } |
||
78 | char word[MAX_DIGITS]; |
||
79 | char *input; |
||
5213 | schaersvoo | 80 | char exp[MAX_DIGITS]; |
5283 | schaersvoo | 81 | int cnt,i,ok,length,zeros,sig1,sig2,found_digit,found_point,dec1,pow,found_power,found_multiply,points,base_start,base_end,bracket; |
82 | const char *invalid_characters = "\n\"\',!=ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz@#$%&;:~><?/\\|"; |
||
5207 | schaersvoo | 83 | /* Ee +- are allowed : 12.34e+05 12.34e-08 1.234*10^123*/ |
84 | cnt = 1; |
||
85 | input = argv[cnt]; |
||
86 | while( input != NULL){ |
||
87 | if(cnt > MAX_CONV){fprintf(stdout,"error : number of conversions exceeds limit of %d\n",MAX_CONV);return 0;} |
||
88 | length = strlen(input); |
||
5219 | schaersvoo | 89 | if( length > MAX_DIGITS){ |
90 | fprintf(stdout,"error : number is larger than %d digits\n",MAX_DIGITS); |
||
91 | return 0; |
||
5207 | schaersvoo | 92 | } |
93 | /* test for illegal characters */ |
||
94 | while (*input){ |
||
95 | if ( strchr(invalid_characters, *input) ){ |
||
96 | fprintf(stdout,"error : found illegal character in argument \"%s\" \n",input); |
||
97 | return 0; |
||
98 | } |
||
99 | input++; |
||
100 | } |
||
101 | input = argv[cnt]; |
||
5356 | schaersvoo | 102 | // better way to use strncpy |
103 | strncpy( word, input, MAX_DIGITS - strlen(word)-1); |
||
5207 | schaersvoo | 104 | // reset |
105 | found_digit = 0; |
||
106 | found_point = 0; |
||
5213 | schaersvoo | 107 | found_power = 0; |
5283 | schaersvoo | 108 | bracket = 0; |
5213 | schaersvoo | 109 | found_multiply = 0; |
110 | sig1 = 0; // real significant digits |
||
111 | sig2 = 0; // integer part [including leading zeros] |
||
5283 | schaersvoo | 112 | dec1 = 0; // decimal part [including trailing zeros] |
5213 | schaersvoo | 113 | pow = 0; // exponent |
114 | zeros = 0; // leading or trailing zeros |
||
5219 | schaersvoo | 115 | points = 0; // number of points in number... |
5213 | schaersvoo | 116 | exp[0]='\0'; |
5219 | schaersvoo | 117 | base_start = 0; |
118 | base_end = 0; |
||
5227 | schaersvoo | 119 | ok = 0; |
5207 | schaersvoo | 120 | for( i = length - 1 ; i >= 0 ; i--){ // walk from rightside to left through the 'number' |
121 | switch( word[i] ){ |
||
5283 | schaersvoo | 122 | case '(' : bracket = 1 ;break; // 10^(-4) -> exp= (-4) : remove bracket from exponent. |
123 | case ')' : bracket = 1 ;break; |
||
124 | case '{' : bracket = 1 ;break; |
||
125 | case '}' : bracket = 1 ;break; |
||
126 | case '[' : bracket = 1 ;break; |
||
127 | case ']' : bracket = 1 ;break; |
||
5219 | schaersvoo | 128 | case '^' : base_start = i;found_power++;break; |
129 | case '*' : |
||
130 | found_multiply++; |
||
131 | if(found_power == 1){ |
||
132 | base_end = i; |
||
133 | if(found_point == 1){points--;found_point = 0;} // point in exponent... 10^4.5 (hmmm) |
||
134 | pow = length - i; |
||
135 | sig1 = 0; // reset counting significant digits and all other stuff |
||
136 | sig2 = 0; |
||
5283 | schaersvoo | 137 | dec1 = 0; |
5219 | schaersvoo | 138 | found_digit = 0; |
139 | zeros = 0; |
||
140 | } |
||
141 | break; |
||
5283 | schaersvoo | 142 | case 'e' : if(found_point == 1){points--;found_point = 0;} found_power++;pow = length - i;sig1 = 0;sig2 = 0;dec1 = 0;found_digit = 0;zeros = 0;found_multiply++;break; |
143 | case 'E' : if(found_point == 1){points--;found_point = 0;} found_power++;pow = length - i;sig1 = 0;sig2 = 0;dec1 = 0;found_digit = 0;zeros = 0;found_multiply++;break; |
||
5207 | schaersvoo | 144 | case '0' : |
12133 | schaersvoo | 145 | if(i == 0){/* last char */ |
5213 | schaersvoo | 146 | sig1 = sig1 - zeros; |
147 | sig2++; |
||
5219 | schaersvoo | 148 | if(found_power == 1){zeros++;} |
5207 | schaersvoo | 149 | } |
150 | else |
||
5219 | schaersvoo | 151 | { |
152 | // 1.000*10^5 -> 4 sig |
||
5283 | schaersvoo | 153 | if( found_point == 0 ){ |
5219 | schaersvoo | 154 | sig1++; |
155 | } |
||
156 | else |
||
157 | { |
||
5283 | schaersvoo | 158 | sig2++; |
5219 | schaersvoo | 159 | if( found_digit == 1 ){ sig1++; } |
160 | } |
||
5207 | schaersvoo | 161 | zeros++; |
162 | } |
||
163 | break; |
||
12133 | schaersvoo | 164 | case '.' : if( i == 0 ){ |
165 | sig1 = sig1 - zeros;sig2++; |
||
166 | if(found_power == 1){ zeros++; } |
||
167 | } /* . is last: so assume 0.xxxxx */ |
||
168 | dec1 = length - i - pow - 1; |
||
169 | found_point = 1;points++; |
||
170 | break; |
||
5213 | schaersvoo | 171 | case '1' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
172 | case '2' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
173 | case '3' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
174 | case '4' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
175 | case '5' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
176 | case '6' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
177 | case '7' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
178 | case '8' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
179 | case '9' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break; |
||
5207 | schaersvoo | 180 | default : break; |
181 | } |
||
5283 | schaersvoo | 182 | if(found_power == 0 && bracket == 0){ append(exp,word[i]); } // maybe a power was used ? |
183 | bracket = 0; |
||
5207 | schaersvoo | 184 | } |
5213 | schaersvoo | 185 | |
5219 | schaersvoo | 186 | if( found_power > 1 || found_multiply > 1){ // 2*2 10^5^7 |
187 | fprintf(stdout,"error \n"); |
||
188 | return 0; |
||
189 | } |
||
190 | |||
191 | if( points > 1){ // "nonsense" number 1.23.45 or 1.23*10^1.5 |
||
5283 | schaersvoo | 192 | fprintf(stdout,"-1,-1,-1,-1,-1,-1\n"); |
5219 | schaersvoo | 193 | } |
194 | else |
||
195 | { |
||
196 | // extra check for handling "special cases" |
||
12133 | schaersvoo | 197 | if(found_point == 1 && found_power == 0 && found_multiply == 0 && ( word[1] == '.' || word[0] == '.' ) ){ok = 1;}// just a decimal number 0.1233 |
5356 | schaersvoo | 198 | else |
5227 | schaersvoo | 199 | if(found_point == 0 && found_power == 0){ sig2 = length;ok = 1; } // just a number 12345 |
200 | else |
||
5283 | schaersvoo | 201 | if(found_point == 0 && found_multiply == 0 && found_power == 1){ sig1 = 0; sig2 = 0 ; dec1 = 0; } // 10^5 |
5227 | schaersvoo | 202 | else |
5283 | schaersvoo | 203 | if(found_point == 1 && found_multiply == 0 && found_power == 1){ sig1 = 0; sig2 = 0 ; dec1 = 0; } // 10^5.1 |
5227 | schaersvoo | 204 | else |
5283 | schaersvoo | 205 | if(found_point == 0 && found_multiply == 1 && found_power == 1){ dec1 = 0; sig2 = length - zeros - pow;} // 3*10^5 |
5356 | schaersvoo | 206 | |
5227 | schaersvoo | 207 | if( found_power == 1){ |
208 | // find out if scientiffic number is correctly written ; ok=0 -> ok=1 |
||
209 | // rule [1-9].[0-9]* x10^exp |
||
12133 | schaersvoo | 210 | if( word[0] != '0' && word[1] == '.' ){ // 0.120*10^5 => 1.20*10^4 |
5227 | schaersvoo | 211 | ok = 1; |
212 | } |
||
213 | else |
||
214 | { |
||
215 | if( (word[0] == '-' || word[0] == '+' ) && word[1] != '0' && word[2] == '.' ){ |
||
216 | ok = 1; // -1.2*10^5 |
||
217 | } |
||
218 | else |
||
219 | { |
||
220 | if( found_point == 0 && found_multiply == 1 ){ |
||
221 | if( word[1] == '*' ){ //4*10^5 |
||
222 | ok = 1; |
||
223 | } |
||
224 | else |
||
225 | { |
||
226 | if( (word[0] == '-' || word[0] == '+' ) && word[2] == '*'){ //-4*10^5 |
||
227 | ok = 1; |
||
228 | } |
||
229 | } |
||
230 | } |
||
231 | } |
||
232 | } |
||
5219 | schaersvoo | 233 | int len = strlen(exp);// reverse appended char array ... 123+ --> +321 |
234 | char exponent[len]; |
||
235 | int w = len - 1; |
||
236 | for(i = 0 ; i < len ; i++){ |
||
237 | exponent[i] = exp[w]; |
||
238 | w--; |
||
239 | } |
||
240 | exponent[len] = '\0'; |
||
241 | if(base_start != 0){ // find the base ( default base = 10 ) |
||
242 | int c = 0;int s; |
||
243 | if(base_end == 0){ // 10^5 |
||
244 | s = 0; |
||
245 | } |
||
246 | else |
||
247 | { |
||
248 | s = base_end + 1; // 1.25*10^5 |
||
249 | } |
||
250 | char c_base[base_start - s]; // assign char array of correct size |
||
251 | for(i = s ; i < base_start ; i++){ |
||
252 | c_base[c] = word[i]; |
||
253 | c++; |
||
254 | } |
||
255 | c_base[c] = '\0'; |
||
5283 | schaersvoo | 256 | fprintf(stdout,"%d,%d,%d,%s,%s,%d\n",sig1,sig2,dec1,c_base,exponent,ok); |
5219 | schaersvoo | 257 | } |
258 | else |
||
259 | { // base = 10 : used 4e+5 |
||
5283 | schaersvoo | 260 | fprintf(stdout,"%d,%d,%d,10,%s,%d\n",sig1,sig2,dec1,exponent,ok); |
5219 | schaersvoo | 261 | } |
5213 | schaersvoo | 262 | } |
263 | else |
||
5219 | schaersvoo | 264 | { // no exponent : base = '1' exponent = '0' |
265 | //several possible correct way of writing... |
||
5283 | schaersvoo | 266 | if( ok == 0 && ( sig1 == sig2 + dec1 ) ){ ok = 1; } |
267 | fprintf(stdout,"%d,%d,%d,1,0,%d\n",sig1,sig2,dec1,ok); |
||
5213 | schaersvoo | 268 | } |
269 | } |
||
5207 | schaersvoo | 270 | cnt++; |
271 | input = argv[cnt]; |
||
272 | } |
||
5219 | schaersvoo | 273 | return 0; |
5207 | schaersvoo | 274 | } |