Rev 13927 | Rev 14856 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 13927 | Rev 13932 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | ********************************************************************************* |
2 | ********************************************************************************* |
3 | * J.M. Evers |
3 | * J.M. Evers 3/2012 * |
4 | * This is all amateur scriblings... So no copyrights. * |
4 | * This is all amateur scriblings... So no copyrights. * |
5 | * This source code file, and compiled objects derived from it, * |
5 | * This source code file, and compiled objects derived from it, * |
6 | * can be used and distributed without restriction, including for commercial use * |
6 | * can be used and distributed without restriction, including for commercial use * |
7 | * No warrenty whatsoever * |
7 | * No warrenty whatsoever * |
8 | ********************************************************************************* |
8 | ********************************************************************************* |
- | 9 | general use: |
|
- | 10 | rounding to 2 decimals (financial math) |
|
- | 11 | tot=!exec moneyprint 0.1,17,123.4,123.99765 |
|
- | 12 | tot -> 0.10,17.00,123.40,124.00 |
|
9 | 13 | ||
10 | general use: |
- | |
11 | moneyprint number1,number2,number3... DECIMALS |
- | |
12 | default rounding to 2 decimals (financial math) |
- | |
13 | - | ||
14 | tot=!exec moneyprint 6.14512 --> 6.15 |
- | |
15 | tot=!exec moneyprint 6.14512 3 --> 6.145 |
- | |
16 | tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0.10,17.00,123.40,124.00 |
- | |
17 | tot=!exec moneyprint 2*10^7,2E-7 --> 2.00*10^7,2.00*10^-7 |
- | |
18 | !set use_comma |
- | |
19 | # only for representation ,the outcome can not be used for further arithmetics/calculations |
- | |
20 | tot=!exec moneyprint 6.14512 --> 6,15 |
- | |
21 | tot=!exec moneyprint 6.14512 3 --> 6,145 |
- | |
22 | tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0,10 17,00 123,40 124,00 |
- | |
23 | tot=!exec moneyprint 2*10^7,2E-7 --> 2,00*10^7 2,00*10^-7 |
- | |
24 | - | ||
25 | bugs & flaws: no calculations are performed , fractions are not supported |
- | |
26 | - | ||
27 | CHANGELOG |
- | |
28 | 2/2012 |
14 | 2/2012 |
29 | modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers |
15 | modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers |
30 | tot=!exec moneyprint 2.1,4.123,5 2 // 2 decimals |
16 | tot=!exec moneyprint 2.1,4.123,5 2 // 2 decimals |
31 | tot -> 2.10,4.12,5.00 |
17 | tot -> 2.10,4.12,5.00 |
32 | tot=!exec moneyprint 2.1,4.123,5 4 // 4 decimals |
18 | tot=!exec moneyprint 2.1,4.123,5 4 // 4 decimals |
33 | tot -> 2.1000,4.1230,5.0000 |
19 | tot -> 2.1000,4.1230,5.0000 |
34 | tot=!exec moneyprint 2.1,4.123,5 |
20 | tot=!exec moneyprint 2.1,4.123,5 |
35 | tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals |
21 | tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals |
36 | 22 | ||
37 | 6/2012 |
23 | 6/2012. |
38 | modified again to support rounding of scientific numbers, like |
24 | modified again to support rounding of scientific numbers, like |
39 | tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3 |
25 | tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3 |
40 | tot -> 1.235e06,1.235e6,0.012e-23 |
26 | tot -> 1.235e06,1.235e6,0.012e-23 |
- | 27 | |
|
41 | assumed only powers of 10 [scientific notation] |
28 | assumed only powers of 10 [scientific notation] |
42 | |
29 | |
43 | 12/2012 |
30 | 12/2012 |
44 |
|
31 | Modified : using only 10^ in powers |
45 |
|
32 | (e+8 -> *10^8 ; e-8 -> *10^-8) |
46 |
|
33 | Extra syntax error signal (using more than 1 'e') |
47 | 34 | ||
48 | 27/2014 |
35 | 27/2014 |
49 |
|
36 | Modified avoiding truncating of numbers like 15.625 --> 16.62 |
50 | 37 | ||
51 | 2/2018 |
- | |
52 | if variable "w_use_comma" is set (eg in phtml !set use_comma=1), the result is a comma 'decimal' separator: |
- | |
53 | moneyprint 1.2345 2 -> 1,23 |
- | |
54 | moneyprint 1.2345 , 2.34567 , 3.4567 , 5 2 -> 1,23 2,35 3,46 5,00 |
- | |
55 | (note: in this case (multiple conversions) we use 'spaces' instead of an item ',' list ) |
- | |
56 | This is INCOMPATIBLE with calculating software : only suitable for REPRESENTATION of (money) numbers |
- | |
57 | If env. variable w_use_comma is not set or not "1" , the behaviour is a number with a decimal point |
- | |
58 | - | ||
59 | 5/2019 use "strlcpy, strlcat" - size-bounded string copying and concatenation |
- | |
60 | */ |
38 | */ |
61 | 39 | ||
62 | #include <stdio.h> |
40 | #include <stdio.h> |
63 | #include <stdlib.h> |
41 | #include <stdlib.h> |
64 | #include <string.h> |
42 | #include <string.h> |
65 | #include <math.h> |
43 | #include <math.h> |
66 | #include <locale.h> |
- | |
67 | - | ||
68 | #define MAX_DIGITS |
44 | #define MAX_DIGITS 32 |
69 | #define MAX_CONV 32 |
45 | #define MAX_CONV 32 |
70 | #define LOCALE "fr_FR.ISO8859-1" |
- | |
71 | - | ||
72 | 46 | ||
73 | int main( int argc , char *argv[]){ |
47 | int main( int argc , char *argv[]){ |
74 | if( argc != 2 && argc != 3){ |
48 | if( argc != 2 && argc != 3){ |
75 | fprintf(stdout,"error !\nusage:\n!exec moneyprint $your_wims_item_list $precision_word\nexample:\nmoney=!exec moneyprint 1.2,30.1,.4,-.23123456 2\nThe result is a comma separated list: 1.20,30.10,0.40,-0.23\n using 2 decimals\nNote: no calculations are done.\nNo spaces allowed \n"); |
49 | fprintf(stdout,"error !\nusage:\n!exec moneyprint $your_wims_item_list $precision_word\nexample:\nmoney=!exec moneyprint 1.2,30.1,.4,-.23123456 2\nThe result is a comma separated list: 1.20,30.10,0.40,-0.23\n using 2 decimals\nNote: no calculations are done.\nNo spaces allowed \n"); |
76 | exit(0); |
50 | exit(0); |
77 | } |
51 | } |
78 | /* test for illegal characters */ |
52 | /* test for illegal characters */ |
79 | const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|"; |
53 | const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|"; |
80 | /* +-*^XxEe are allowed : 12.34e+05 12.34e-08 1x10^5 1.234*10^123*/ |
54 | /* +-*^XxEe are allowed : 12.34e+05 12.34e-08 1x10^5 1.234*10^123*/ |
81 | char *input; |
55 | char *input; |
82 | input = argv[1]; |
56 | input = argv[1]; |
83 | while (*input){ |
57 | while (*input){ |
84 | if ( strchr(invalid_characters, *input) ){ |
58 | if ( strchr(invalid_characters, *input) ){ |
85 | fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input); |
59 | fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input); |
86 | exit(0); |
60 | exit(0); |
87 | } |
61 | } |
88 | input++; |
62 | input++; |
89 | } |
63 | } |
90 | int DECIMALS; |
64 | int DECIMALS; |
91 | if(argv[2] != NULL){ |
65 | if(argv[2] != NULL){ |
92 | DECIMALS = atoi(argv[2]); |
66 | DECIMALS = atoi(argv[2]); |
93 | if(DECIMALS > MAX_DIGITS){ |
67 | if(DECIMALS > MAX_DIGITS){ |
94 | fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0); |
68 | fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0); |
95 | } |
69 | } |
96 | } |
70 | } |
97 | else |
71 | else |
98 | { |
72 | { |
99 | DECIMALS = 2; |
73 | DECIMALS = 2; |
100 | } |
74 | } |
101 | char *sep = ","; |
- | |
102 | char *ptr; |
75 | char *ptr; |
103 | char word[MAX_DIGITS]; |
76 | char word[MAX_DIGITS]; |
104 | char exponent[MAX_DIGITS]; |
77 | char exponent[MAX_DIGITS]; |
105 | char number[MAX_DIGITS]; |
78 | char number[MAX_DIGITS]; |
- | 79 | int cnt = 1; |
|
106 |
|
80 | int powE = 0; |
- | 81 | int idx1 = 0; |
|
- | 82 | int idx2 = 0; |
|
107 |
|
83 | int length= 0; |
- | 84 | int i = 0; |
|
108 |
|
85 | int pow10 = 0; |
109 | double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */ |
86 | double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */ |
110 | double ascii_number; |
87 | double ascii_number; |
111 | input = argv[1]; |
88 | input = argv[1]; |
112 | ptr = strtok(input,","); |
89 | ptr = strtok(input,","); |
113 | while( ptr != NULL){ |
90 | while( ptr != NULL){ |
- | 91 | if( cnt > MAX_CONV ){ |
|
114 |
|
92 | fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV); |
- | 93 | exit(0); |
|
- | 94 | } |
|
115 |
|
95 | // next item in input argv[1] |
116 |
|
96 | strncpy( word, ptr, MAX_DIGITS); |
117 | length = strlen(ptr); |
97 | length = strlen(ptr); |
- | 98 | if(length > MAX_DIGITS-1){ |
|
118 |
|
99 | fprintf(stdout,"ERROR string too large\n"); |
- | 100 | exit(0); |
|
- | 101 | } |
|
119 |
|
102 | //reset counters |
- | 103 | powE = 0; |
|
120 |
|
104 | pow10 = 0; |
- | 105 | idx1 = 0; |
|
- | 106 | idx2 = 0; |
|
- | 107 | i = 0; |
|
121 | for( i = 0; i < length ; i++){ |
108 | for( i = 0; i < length ; i++){ |
- | 109 | if(powE > 1 ){ |
|
122 |
|
110 | fprintf(stdout,"ERROR in syntax\n"); |
- | 111 | exit(0); |
|
- | 112 | } |
|
- | 113 | if( idx1 + idx2 > MAX_DIGITS-1){ |
|
123 |
|
114 | fprintf(stdout,"ERROR string too large\n"); |
- | 115 | exit(0); |
|
- | 116 | } |
|
124 | switch( word[i] ){ |
117 | switch( word[i] ){ |
125 | case '+' : break; /* do not use 10^+2 */ |
118 | case '+' : break; /* do not use 10^+2 */ |
126 | case 'e' : powE++;break; |
119 | case 'e' : powE++;break; |
127 | case 'E' : powE++;break; |
120 | case 'E' : powE++;break; |
128 | case 'x' : pow10++;break; |
121 | case 'x' : pow10++;break; |
129 | case '*' : pow10++;break; |
122 | case '*' : pow10++;break; |
130 |
|
123 | case '^' : pow10=5;break; |
131 |
|
124 | default : |
132 |
|
125 | if( pow10 > 0 ){ |
133 | pow10++; |
126 | pow10++; |
134 | if( pow10 > 4 ){ /* *10^ = 4 chars */ |
127 | if( pow10 > 4 ){ /* *10^ = 4 chars */ |
135 | exponent[idx2] = word[i]; |
128 | exponent[idx2] = word[i]; |
136 | idx2++; |
129 | idx2++; |
137 | } |
- | |
138 | } |
130 | } |
139 | else |
- | |
140 | { |
- | |
141 | if(powE > 0){ |
- | |
142 | exponent[idx2] = word[i]; |
- | |
143 | idx2++; |
- | |
144 | } |
131 | } |
145 | else |
132 | else |
146 | { |
133 | { |
- | 134 | if(powE > 0){ |
|
- | 135 | exponent[idx2] = word[i]; |
|
- | 136 | idx2++; |
|
- | 137 | } |
|
- | 138 | else |
|
- | 139 | { |
|
147 | number[idx1] = word[i]; |
140 | number[idx1] = word[i]; |
148 | idx1++; |
141 | idx1++; |
- | 142 | } |
|
149 | } |
143 | } |
150 | } |
- | |
151 | break; |
144 | break; |
152 | } |
145 | } |
153 | } |
146 | } |
154 | exponent[idx2] = '\0'; |
147 | exponent[idx2] = '\0'; |
155 | number[idx1] = '\0'; |
148 | number[idx1] = '\0'; |
156 |
|
149 | ascii_number = atof(number); |
157 |
|
150 | if( ascii_number > 0 ){ |
158 |
|
151 | ascii_number = ascii_number + correction; |
- | 152 | } |
|
- | 153 | else |
|
- | 154 | { |
|
159 |
|
155 | ascii_number = ascii_number - correction; |
160 |
|
156 | } |
161 | if( powE == 1 || pow10> 0 ){ |
157 | if( powE == 1 || pow10> 0 ){ |
162 | if(cnt > 1){ |
158 | if(cnt > 1){ |
163 | fprintf |
159 | fprintf( stdout , ",%.*f*10^%s" , DECIMALS , ascii_number , exponent ); |
164 | } |
160 | } |
165 | else |
161 | else |
166 | { |
162 | { |
167 | fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent ); |
163 | fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent ); |
168 | } |
164 | } |
169 | } |
165 | } |
170 | else |
166 | else |
171 | { |
167 | { |
172 | if(cnt > 1 ){ |
168 | if(cnt > 1 ){ |
173 | fprintf |
169 | fprintf( stdout , ",%.*f" , DECIMALS , ascii_number); |
174 | } |
170 | } |
175 | else |
171 | else |
176 | { |
172 | { |
177 | fprintf |
173 | fprintf( stdout , "%.*f" , DECIMALS , ascii_number); |
178 | } |
174 | } |
179 | } |
175 | } |
180 | cnt++; |
176 | cnt++; |
181 | ptr = strtok(NULL,","); |
177 | ptr = strtok(NULL,","); |
182 | } |
178 | } |
183 | fprintf(stdout,"\n"); |
179 | fprintf(stdout,"\n"); |
184 | return 0; |
180 | return 0; |
185 | } |
181 | } |
- | 182 | ||
186 | 183 |