Subversion Repositories wimsdev

Rev

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