Subversion Repositories wimsdev

Rev

Rev 6738 | Rev 7038 | 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
*********************************************************************************
6738 schaersvoo 10
20/6/2012
11
Corrected significance flaw when using prefixes
12
Simplified routines
13
Added type = 5 : prefix-notation with words (nano,mega,giga...etc)
5196 schaersvoo 14
 
5950 schaersvoo 15
12/11/2012
16
Added support for numbers like  12345*10^12
17
12345*10^12 --> 12345E12 ---> 1.2345*10^16
18
 
5801 schaersvoo 19
18/10/2012 :
20
Added Mathml output
21
Added option significance=-1
22
To be used when there is no significance known ; just tries to print the number in science notation
5840 schaersvoo 23
Using the original amount of digits used in "number" argument
24
!exec scienceprint 123.445000e+23,-1 --> 1.23445000*10^25
5801 schaersvoo 25
 
7037 schaersvoo 26
27/9/2013
27
Correct rounding in stead of truncation...
28
 
5801 schaersvoo 29
*********************************************************************************
30
 
5177 schaersvoo 31
WIMS usage:
32
sci_num = !exec scienceprint number,significance,type
5196 schaersvoo 33
 
5171 schaersvoo 34
number: a number
5196 schaersvoo 35
significance : desired precision
5801 schaersvoo 36
type (optional args): calc = 0 / html = 1 / latex = 2  / prefix = 3  / mathml = 4
5177 schaersvoo 37
 
5196 schaersvoo 38
default  : calc   notation : 120000,3   -> 1.20*10^5
39
type = 0 : calc   notation : 120000,3,0 -> 1.20*10^5
40
type = 1 : html notation   : 120000,3,1 -> 1.20&times;10<sup>5</sup>
41
type = 2 : latex notation  : 120000,3,2 -> 1.20 \times 10^{5}
5171 schaersvoo 42
type = 3 : prefix-notation : 120000,3,3 -> 120.0 k
5196 schaersvoo 43
type = 3 : if -24 > prefix > 24         -> type = 1 (html)
5801 schaersvoo 44
type = 4 : mathml notation
5171 schaersvoo 45
 
46
multiple conversion: use space between arguments
5177 schaersvoo 47
scienceprint 120000,4 122900,5 120036,6,3 --> 120.0*10^3,122.90*10^3,120.036 k
5171 schaersvoo 48
 
5196 schaersvoo 49
24  yotta       Y
50
21  zetta       Z
51
18  exa         E
52
15  peta        P
53
12  tera        T
54
9   giga        G
55
6   mega        M
56
3   kilo        k
6738 schaersvoo 57
 
5196 schaersvoo 58
2   hecto       h
59
1   deca        da
60
-1  deci        d
61
-2  centi       c
6738 schaersvoo 62
 
5196 schaersvoo 63
-3  milli       m
64
-6  micro       µ
65
-9  nano        n
66
-12 pico        p
67
-15 femto       f
68
-18 atto        a
69
-21 zepto       z
70
-24 yocto       y
71
 
5171 schaersvoo 72
*/
73
 
74
#include <stdio.h>
75
#include <math.h>
76
#include <string.h>
77
#include <stdlib.h>
78
#define MICRO "µ"
5196 schaersvoo 79
#define MAX_CONV 256
5950 schaersvoo 80
#define MAX_STRING 32
6738 schaersvoo 81
#define PREFIX_START -24
82
#define PREFIX_END 24
5171 schaersvoo 83
 
5950 schaersvoo 84
char *str_replace ( const char *word, const char *sub_word, const  char *rep_word ){
85
    if(strlen(word) > MAX_STRING){return NULL;}
86
    char *part_word = NULL;
87
    char *new_word = NULL;
88
    char *old_word = NULL;
89
    char *head = NULL;
90
    /* if either sub_word or rep_word is NULL, duplicate word a let caller handle it */
91
    if ( sub_word == NULL || rep_word == NULL ) return strdup(word);
92
    new_word = strdup (word);
93
    head = new_word;
94
    while ( (part_word = strstr ( head, sub_word ))){
95
        old_word = new_word;
96
        new_word = malloc ( strlen ( old_word ) - strlen ( sub_word ) + strlen ( rep_word ) + 1 );
97
        /*failed to alloc mem, free old word and return NULL */
98
        if ( new_word == NULL ){
99
          free (old_word);return NULL;
100
        }
101
        memcpy ( new_word, old_word, part_word - old_word );
102
        memcpy ( new_word + (part_word - old_word), rep_word, strlen ( rep_word ) );
103
        memcpy ( new_word + (part_word - old_word) + strlen( rep_word ), part_word + strlen ( sub_word ), strlen ( old_word ) - strlen ( sub_word ) - ( part_word - old_word ) );
104
        memset ( new_word + strlen ( old_word ) - strlen ( sub_word ) + strlen ( rep_word ) , 0, 1 );
105
        /* move back head right after the last replacement */
106
        head = new_word + (part_word - old_word) + strlen( rep_word );
107
        free (old_word);
108
    }
109
    return new_word;
110
}
111
 
5801 schaersvoo 112
char *printscience(double value, int sig, int format , int cnt ,int size){
6738 schaersvoo 113
    static char *min[] = {"","m",MICRO,"n","p","f","a","z","y"};
114
    static char *plus[] = {"","k", "M", "G", "T", "P", "E", "Z", "Y" };
115
    static char *min_word[] = {"","milli","micro","nano","pico","femto","atto","zepto","yocto"};
116
    static char *plus_word[] = {"","kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta" };
117
    char *sign = NULL;char *prefix = NULL;
118
    int exponent10 = 0;
7037 schaersvoo 119
    int factor = pow(10,sig);
6738 schaersvoo 120
    int use_word = 0;if(format == 5){format = 3; use_word = 1;} /* switch to using words in stead of prefix  */
121
    if(value < 0.0) {sign = "-";value = -value;sig--;} else {sign = "";}    if( sig == -1 ){
122
     /*
123
     no significance truncations...just science notation 1234 -> 1.234*10^3
124
     try (!) to use same amount of digits
125
     */
5801 schaersvoo 126
        sig = size;
6738 schaersvoo 127
        if(format == 3){format = 1;} /* never prefix --> html notation */
128
    }
129
    if(value == 0){fprintf(stdout, "%s%.*f", sign, sig-1, value);return NULL;} /* no need to go further */
130
    if(value>1){
131
        while(value >= 10){
132
            value=value / 10.0;
133
            exponent10++;
134
            /* need to set a limit to number of while loops ! */
135
            if(exponent10 > 100){fprintf(stdout,"error : number too big (exponent > 100)\n");return 0;}
5196 schaersvoo 136
        }
5177 schaersvoo 137
    }
6738 schaersvoo 138
    else /* 0 < value < 1 --> exponent10 < 0 */
5177 schaersvoo 139
    {
6738 schaersvoo 140
        while(value < 1){
141
            value=value*10;
142
            exponent10--;
143
            /* need to set a limit to number of while loops ! */
144
            if(exponent10 <-100){fprintf(stdout,"error : number too small (exponent < -100)\n");return 0;}
5171 schaersvoo 145
        }
5177 schaersvoo 146
    }
7037 schaersvoo 147
    /* 27/9/2013 avoid truncating and do normal rounding...grrr */
148
    value = (round(factor*value))/factor;
6738 schaersvoo 149
    if(format == 3 && ((exponent10 < PREFIX_START) || (exponent10 > PREFIX_END))){
150
        format = 1; /* not in my list of prefixes ; print in html ! */
5196 schaersvoo 151
    }
6738 schaersvoo 152
    sig = sig - 1; /* "%.*f" counts the "." */
153
    if(cnt > 1){fprintf(stdout,",");}/* more than one conversion to do : make list */
154
    int idx=0;int exp=0;
155
    if(exponent10 == 0){format = 6;} /* no need for 2*10^0 */
156
    if(sig < 0){sig = 0;} /* better be safe than sorry... */
157
    switch(format){
158
        case 0: fprintf(stdout, "%s%.*f*10^%d", sign, sig, value, exponent10);break;
159
        case 1: fprintf(stdout, "%s%.*f&times;10<sup>%d</sup>", sign, sig, value, exponent10);break;
160
        case 2: fprintf(stdout, "%s%.*f \\times 10^{%d}", sign, sig, value, exponent10);break;
161
        case 3:
162
/*
163
1,1,3 -> 1
164
10,1,3 -> 1*10^-2 k
165
100,1,3 -> 1*10^-1 k
166
1000,1,3 -> 1 k
167
10000,1,3 -> 1*10^1 k
168
100000,1,3 -> 1*10^2 k
169
1000000,1,3 -> 1 M
170
10000000,1,3 -> 1*10^1 M
171
100000000,1,3 -> 1*10^2 M
172
1000000000,1,3 -> 1 G
173
1,1,3 -> 1
174
0.1,1,3 -> 1*10^-1
175
0.01,1,3 -> 1*10^-2
176
0.001,1,3 -> 1 m
177
0.0001,1,3 -> 1*10^-1 m
178
0.00001,1,3 -> 1*10^-2 m
179
0.000001,1,3 -> 1 µ
180
0.0000001,1,3-> 1*10^-1 µ
181
0.00000001,1,3-> 1*10^-2 µ
182
0.000000001,1,3-> 1 n
183
*/
184
        exp = exponent10%3;
185
        idx = round(exponent10/3);
186
        if( exponent10 > 0  ){
187
            if(use_word == 0 ){ prefix = plus[idx]; } else { prefix = plus_word[idx]; }
5196 schaersvoo 188
        }
5206 schaersvoo 189
        else
190
        {
6738 schaersvoo 191
            if(use_word == 0){ prefix = min[-1*idx]; } else { prefix = min_word[-1*idx]; }
5206 schaersvoo 192
        }
6738 schaersvoo 193
        if( exp == 0){
194
            fprintf(stdout, "%s%.*f %s",sign, sig, value,prefix);
5171 schaersvoo 195
        }
196
        else
197
        {
6738 schaersvoo 198
            fprintf(stdout, "%s%.*f&times;10<sup>%d</sup> %s", sign, sig, value, exp, prefix);
5171 schaersvoo 199
        }
6738 schaersvoo 200
        break;
201
        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>&times;</mo><msup><mn>10</mn><mn>%d</mn></msup></mstyle></math>", sign, sig, value, exponent10);break;
202
        case 5: break;
203
        case 6: fprintf(stdout, "%s%.*f",sign,sig,value);break;
204
        default: break;
5801 schaersvoo 205
    }
5177 schaersvoo 206
    return NULL;
207
}
208
 
209
int main( int argc , char *argv[]){
5171 schaersvoo 210
 
5177 schaersvoo 211
    if( argc < 2){
212
        fprintf(stdout,"syntax error : number1,significance1,type1 number2,significance2,type2 ... number_n,significance_n,type_n \n");
213
        return 0;
214
    }
5801 schaersvoo 215
 
5171 schaersvoo 216
    double number = 0;
5801 schaersvoo 217
    int significance = 0,type = 0,idx = 0,cnt = 1,size = 0;
5171 schaersvoo 218
    char *input = "\0",*ptr = "\0";
219
 
220
    /* test for illegal characters */
5950 schaersvoo 221
    const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz@#$%&()[]{};:~><?/\\|";
5171 schaersvoo 222
    /* Ee +- are allowed : 12.34e+05  12.34e-08 */
223
 
224
    /* walk through argument 1 to end, and call function scienceprint(a,b,c) */
225
    input = argv[cnt];
226
    while( input != NULL ){
5196 schaersvoo 227
        if(cnt > MAX_CONV){fprintf(stdout,"\nerror: number of conversions exceeds limit of %d\n",MAX_CONV);return 0;}
5801 schaersvoo 228
        while (*input){ /* loop through invalid chars. */
5171 schaersvoo 229
            if ( strchr(invalid_characters, *input) ){
5801 schaersvoo 230
                fprintf(stdout,"\nerror : illegal character \"%s\" \n",input);
5196 schaersvoo 231
                return 0;
5171 schaersvoo 232
            }
233
            input++;
234
        }
5801 schaersvoo 235
        /* reset input to actual value */
5171 schaersvoo 236
        input = argv[cnt];
237
        ptr = (char *) strtok(input,",");
238
        idx = 0;
239
        type = 0;
5801 schaersvoo 240
        size = 0;
5171 schaersvoo 241
        while( ptr != NULL ){
242
            switch( idx ){
5950 schaersvoo 243
                case 0:
5840 schaersvoo 244
                        /* size only interesting when 'significance=-1'
245
                         determine number of digits : 1.23445e+23 -> size = 6
246
                        */
5950 schaersvoo 247
                        size = strlen(ptr);
248
                        if( strstr(ptr,".") != NULL){size = size - 1 ;}
249
                        if( strstr(ptr,"*10^") != NULL){
250
                            ptr = str_replace(ptr,"*10^","E");
251
                            if(ptr == NULL){
252
                                fprintf(stdout,"error : in replacement of 10^ notation\n");
253
                                return 0;
254
                            }
255
                            size = size - 3;
256
                        }
5840 schaersvoo 257
                        if( strstr(ptr,"E") != NULL){size = size - strlen(strstr(ptr,"E"));}
258
                        if( strstr(ptr,"e") != NULL){size = size - strlen(strstr(ptr,"e"));}
5950 schaersvoo 259
                        number = atof(ptr);
5840 schaersvoo 260
                        break;
5801 schaersvoo 261
                case 1: significance = atoi(ptr);  break;
6738 schaersvoo 262
                case 2: type = atoi(ptr); if(type < 0 || type > 5 ){type = 0;} break;
5171 schaersvoo 263
                default: break;
264
            }
265
            idx++;
266
            ptr = (char *) strtok(NULL,",");
267
        }
5801 schaersvoo 268
        /* number and precision are mandatory:  default type=0  */
5196 schaersvoo 269
        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 270
        /* call conversion routine */
271
        printscience(number, significance, type , cnt , size);
5171 schaersvoo 272
        cnt++;
273
        input = argv[cnt];
274
    }
275
    fprintf(stdout,"\n");
276
    return 0;
277
}
5950 schaersvoo 278
 
279
 
280