Subversion Repositories wimsdev

Rev

Rev 15712 | Details | Compare with Previous | Last modification | View Log | RSS feed

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