Subversion Repositories wimsdev

Rev

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
}