Subversion Repositories wimsdev

Compare Revisions

Ignore whitespace Rev 5212 → Rev 5213

/trunk/wims/src/Misc/sigdigits/sigdigits.c
6,55 → 6,32
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatsoever *
*********************************************************************************
syntax number_1 number2 number_3 ... number_n
 
example
!exec sigdigits 0001.0200 01.0200*10^-4 1.023*10^5
3,2,4,4,0,0
3,2,2,4,-4,0
4,3,1,3,5,1
 
usage:
1) discard trailing zeros : use no flags (default)
!exec sigdigits 1.10000 2.0001000 123.0100010000
2,1
5,4
9,6
result is
1 line per input number
6 items per line:
 
or use flag "0"
!exec sigdigits 1.10000,0 2.0001000,0 123.0100010000,0
2,1
5,4
9,6
item 1) real number of significant digits in number_x (eg without leading zeros)
item 2) real number of "significant decimals" (eg without trailing zero's)
 
2) include trailing zeros : use flag "1" (due to accuracy measurement...)
!exec sigdigits 1.10000,1 2.0001000,1 123.0100010000,1
7,5
9,7
14,10
item 3) number of digits left from decimal point (including non-significant)
or if no decimals: total number of digits (length)
item 4) number of digits right from decimal point (including non-significant)
 
3) scientific notation allowed:
!exec sigdigits 1.2300000*10^15
3,2
!exec sigdigits 1.2300001*10^15
8,7
!exec sigdigits 1.2300000e+15
3,2
!exec sigdigits 1.2300001e+15
8,7
item 5) exponent (if not present : 0)
 
4) all other 'numbers' using pi,log,ln,sin,etc...will produce an error
item 6) indication : is the number correctly written ? 1 or 0 ( 000.1 is not correct...)
 
5)output "2 items per line"
first item is total amount of significant digits
second item is amount of decimals
exponent '10^' or 'e': 1.23*10^-4 1.23e-4
*/
 
6) no evaluation on the 'size' of the number is performed.
 
It can be used in an answer checkfile,
to check if the pupil uses the correct amount of significant digits in the reply .
Example:
A circle with "R=2.01 cm" has a surface area of ?
The 'math' answer is approx 12.69234847976812366271292553 cm2
The 'physics' answer is 12.7 ... using 3 significant digits
(due to the precision of the given R. note: there is no checking of the unit 'cm')
 
 
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
61,6 → 38,11
#define MAX_DIGITS 64
#define MAX_CONV 64
 
void append(char* s, char c){
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
 
int main( int argc , char *argv[]){
if( argc < 2){
69,7 → 51,8
}
char word[MAX_DIGITS];
char *input;
int use_all_zeros,cnt,i,length,zeros,significance,found_digit,found_point,decimals;
char exp[MAX_DIGITS];
int cnt,i,ok,length,zeros,sig1,sig2,found_digit,found_point,dec1,dec2,pow,found_power,found_multiply;
const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz@#$%&()[]{};:~><?/\\|";
/* Ee +- are allowed : 12.34e+05 12.34e-08 1.234*10^123*/
cnt = 1;
94,58 → 77,76
// reset
found_digit = 0;
found_point = 0;
decimals = 0;
significance = 0;
zeros = 0;
use_all_zeros = 0; // trailing zeros are not significant...unless
found_power = 0;
found_multiply = 0;
sig1 = 0; // real significant digits
dec1 = 0; // real "significant decimals"
sig2 = 0; // integer part [including leading zeros]
dec2 = 0; // decimal part [including trailing zeros]
pow = 0; // exponent
zeros = 0; // leading or trailing zeros
exp[0]='\0';
for( i = length - 1 ; i >= 0 ; i--){ // walk from rightside to left through the 'number'
switch( word[i] ){
case '*' : significance = 0;decimals = 0;found_digit = 0;zeros = 0;break;
case 'e' : significance = 0;decimals = 0;found_digit = 0;zeros = 0;break;
case 'E' : significance = 0;decimals = 0;found_digit = 0;zeros = 0;break;
case ',' : // signaling a flag '1'
if( i+1 < length ){
if(word[i + 1] == '1'){ use_all_zeros = 1;}
}
significance = 0;
decimals = 0;
found_digit = 0;
zeros = 0;
break;
case '^' : found_power = 1;break;
case '*' : found_power = 1;pow = length - i;sig1 = 0;dec1 = 0;found_digit = 0;zeros = 0;found_multiply = 1;break;
case 'e' : found_power = 1;pow = length - i;sig1 = 0;dec1 = 0;found_digit = 0;zeros = 0;found_multiply = 1;break;
case 'E' : found_power = 1;pow = length - i;sig1 = 0;dec1 = 0;found_digit = 0;zeros = 0;found_multiply = 1;break;
case '0' :
if(i == 0){//last char
significance = significance - zeros;
if(i == 0){//last char
sig1 = sig1 - zeros;
sig2++;
}
else
{
if( found_digit == 1 ){
significance++;
}
else
{
if( found_point == 0 && use_all_zeros == 1){
significance++;
}
}
if( found_point == 1 ){ sig2++; }
if( found_digit == 1 ){ sig1++; }
zeros++;
}
break;
case '.' : decimals = significance; found_point = 1; break;
case '1' : significance++;found_digit = 1;zeros = 0; break;
case '2' : significance++;found_digit = 1;zeros = 0; break;
case '3' : significance++;found_digit = 1;zeros = 0; break;
case '4' : significance++;found_digit = 1;zeros = 0; break;
case '5' : significance++;found_digit = 1;zeros = 0; break;
case '6' : significance++;found_digit = 1;zeros = 0; break;
case '7' : significance++;found_digit = 1;zeros = 0; break;
case '8' : significance++;found_digit = 1;zeros = 0; break;
case '9' : significance++;found_digit = 1;zeros = 0; break;
case '.' : dec1 = sig1; dec2 = length - i - pow - 1;found_point = 1; break;
case '1' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '2' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '3' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '4' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '5' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '6' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '7' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '8' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
case '9' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
default : break;
}
if(found_power == 0){ append(exp,word[i]); } // maybe a power was used ?
}
if(found_point == 0){ sig2 = length; } // just a number 12345
//several possible correct way of writing...
if( ( sig1 == sig2 + dec2 ) || ( sig1 + dec1 == sig2 + dec2 ) || ( dec1 == dec2 && sig2 == 1 ) ){ ok = 1; } else { ok = 0; }
if( found_power == 1){ // reverse appended char array ... 123+ --> +321
int len = strlen(exp);
char exponent[len];
int w = len - 1;
for(i = 0 ; i < len ; i++){
exponent[i] = exp[w];
w--;
}
exponent[len] = '\0';
if( found_multiply == 0 ){ // e+4 10^6
fprintf(stdout,"0,%d,%d,%d,%s,1\n",dec1,sig2,dec2,exponent);
}
else
{ // 1.23e6 1.23*10^5
fprintf(stdout,"%d,%d,%d,%d,%s,%d\n",sig1,dec1,sig2,dec2,exponent,ok);
}
}
else
{
fprintf(stdout,"%d,%d,%d,%d,0,%d\n",sig1,dec1,sig2,dec2,ok);
}
cnt++;
input = argv[cnt];
fprintf(stdout,"%d,%d\n",significance,decimals);
}
return (0);
}