Subversion Repositories wimsdev

Rev

Rev 5219 | Rev 5283 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2. *********************************************************************************
  3. * J.M. Evers 3/2012                                                             *
  4. * This is all amateur scriblings... So no copyrights.                           *
  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                                                        *
  8. *********************************************************************************
  9. syntax number_1 number2 number_3 ... number_n
  10.  
  11. Treats a number as string array : no numerical evaluation !
  12. (pfffff...)
  13.  
  14. example
  15. !exec sigdigits 1.23 1.230 1.2300 1.23e5 1.23*10^5 1.2300e5 01.23*10^5 1.2.3.4
  16. 3,2,1,2,1,0,1
  17. 3,2,1,3,1,0,0
  18. 3,2,1,4,1,0,1
  19. 3,2,1,2,10,5,1
  20. 3,2,1,2,10,5,1
  21. 5,4,1,4,10,5,1
  22. 3,2,2,2,10,5,0
  23. -1,-1,-1,-1,-1,-1,-1
  24.  
  25. result is
  26. 1 line per input number
  27. 7 items per line:
  28.  
  29. item 1) real number of significant digits in number_x (eg without leading zeros)
  30.  
  31. item 2) real number of "significant decimals" (eg without trailing zero's)
  32.  
  33. item 3) number of digits left from decimal point (including non-significant)
  34.         or if no decimals: total number of digits (length)
  35. item 4) number of digits right from decimal point (including non-significant)
  36.  
  37. item 5) exponent base (if not present : 1)
  38.  
  39. item 6) exponent (if not present : 0)
  40.  
  41. item 7) indication : is the number correctly written ?  1 or 0  ( 000.1 is not correct...)
  42.         scientiffic: [1-9.*] *10^exp : 1.2345*10^5 is OK ... 12.345*10^4 or 0.12345*10^6 is "NOK"
  43.         a*10^b  : 1 <= a <= 9
  44.  
  45. remarks:
  46. - exponent: any other base will be tolerated : 4*7^5  base=7 exponent=5 -> 1,0,1,0,7,5,1
  47. - if number is 'nonsense' : -1,-1,-1,-1,-1,-1 (1.23.4567  10^1.23.4 ; number will produce NaN in other math software)
  48.  
  49. ruleset:
  50. 120.2           : 4 significant digits
  51. 120.2000        : 4 significant digits
  52. 0120.2          : 4 significant digits
  53. scientiffic notation:
  54. 1.202*10^5      : 4 significant digits
  55. 1.20200*10^5    : 6 significant digits
  56.  
  57.  
  58. */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #define MAX_DIGITS 64
  64. #define MAX_CONV 64
  65.  
  66. void append(char* s, char c){
  67.     int len = strlen(s);
  68.     s[len] = c;
  69.     s[len+1] = '\0';
  70. }
  71.  
  72. int main( int argc , char *argv[]){
  73.     if( argc < 2){
  74.         fprintf(stdout,"syntax error\n");
  75.         exit(0);
  76.     }
  77.     char word[MAX_DIGITS];
  78.     char *input;
  79.     char exp[MAX_DIGITS];
  80.     int cnt,i,ok,length,zeros,sig1,sig2,found_digit,found_point,dec1,dec2,pow,found_power,found_multiply,points,base_start,base_end;
  81.     const char *invalid_characters = "\n\"\',!=ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz@#$%&()[]{};:~><?/\\|";
  82.     /* Ee +- are allowed : 12.34e+05  12.34e-08  1.234*10^123*/
  83.     cnt = 1;
  84.     input = argv[cnt];
  85.     while( input != NULL){
  86.         if(cnt > MAX_CONV){fprintf(stdout,"error : number of conversions exceeds limit of %d\n",MAX_CONV);return 0;}
  87.         length = strlen(input);
  88.         if( length > MAX_DIGITS){
  89.             fprintf(stdout,"error : number is larger than %d digits\n",MAX_DIGITS);
  90.             return 0;
  91.                                                                                                                            
  92.         }
  93.         /* test for illegal characters */
  94.         while (*input){
  95.             if ( strchr(invalid_characters, *input) ){
  96.                 fprintf(stdout,"error : found illegal character in argument \"%s\" \n",input);
  97.                 return 0;
  98.             }
  99.             input++;
  100.         }
  101.         input = argv[cnt];
  102.         strncpy( word, input, length );
  103.         // reset
  104.         found_digit = 0;
  105.         found_point = 0;
  106.         found_power = 0;
  107.         found_multiply = 0;
  108.         sig1 = 0; // real significant digits
  109.         dec1 = 0; // real "significant decimals"
  110.         sig2 = 0; // integer part [including leading zeros]
  111.         dec2 = 0; // decimal part [including trailing zeros]
  112.         pow = 0; // exponent
  113.         zeros = 0; // leading or trailing zeros
  114.         points = 0; // number of points in number...
  115.         exp[0]='\0';
  116.         base_start = 0;
  117.         base_end = 0;
  118.         ok = 0;
  119.         for( i = length - 1 ; i >= 0 ; i--){ // walk from rightside to left through the 'number'
  120.             switch( word[i] ){
  121.                 case '^' : base_start = i;found_power++;break;
  122.                 case '*' :
  123.                     found_multiply++;
  124.                     if(found_power == 1){
  125.                         base_end = i;
  126.                         if(found_point == 1){points--;found_point = 0;}  // point in exponent... 10^4.5 (hmmm)
  127.                         pow = length - i;
  128.                         sig1 = 0; // reset counting significant digits and all other stuff
  129.                         dec1 = 0;
  130.                         sig2 = 0;
  131.                         dec2 = 0;
  132.                         found_digit = 0;
  133.                         zeros = 0;
  134.                     }
  135.                     break;
  136.                 case 'e' : if(found_point == 1){points--;found_point = 0;} found_power++;pow = length - i;sig1 = 0;dec1 = 0;sig2 = 0;dec2 = 0;found_digit = 0;zeros = 0;found_multiply++;break;
  137.                 case 'E' : if(found_point == 1){points--;found_point = 0;} found_power++;pow = length - i;sig1 = 0;dec1 = 0;sig2 = 0;dec2 = 0;found_digit = 0;zeros = 0;found_multiply++;break;
  138.                 case '0' :
  139.                     if(i == 0){//last char
  140.                         sig1 = sig1 - zeros;
  141.                         sig2++;
  142.                         if(found_power == 1){zeros++;}
  143.                     }
  144.                     else
  145.                     {              
  146.                         // 1.000*10^5 -> 4 sig
  147.                         if( found_point == 0 && found_power == 1){
  148.                             sig1++;
  149.                         }
  150.                         else
  151.                         {
  152.                             if( found_digit == 1 ){ sig1++; }
  153.                         }
  154.                         if( found_point == 1 ){ sig2++; }
  155.                         zeros++;
  156.                     }
  157.                     break;
  158.                 case '.' : dec1 = sig1; dec2 = length - i - pow - 1;found_point = 1;points++; break;
  159.                 case '1' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  160.                 case '2' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  161.                 case '3' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  162.                 case '4' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  163.                 case '5' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  164.                 case '6' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  165.                 case '7' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  166.                 case '8' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  167.                 case '9' : sig1++;if(found_point == 1){sig2++;} found_digit = 1;zeros = 0; break;
  168.                 default :  break;
  169.             }
  170.             if(found_power == 0){ append(exp,word[i]); } // maybe a power was used ?
  171.         }
  172.        
  173.         if( found_power > 1 || found_multiply > 1){ // 2*2 10^5^7
  174.             fprintf(stdout,"error \n");
  175.             return 0;
  176.         }
  177.  
  178.         if( points > 1){ // "nonsense" number 1.23.45  or 1.23*10^1.5
  179.             fprintf(stdout,"-1,-1,-1,-1,-1,-1,-1\n");
  180.         }
  181.         else
  182.         {
  183.             // extra check for handling "special cases"
  184.             if(found_point == 0 && found_power == 0){ sig2 = length;ok = 1; }   // just a number 12345
  185.             else
  186.             if(found_point == 0 && found_multiply == 0 && found_power == 1){ sig1 = 0; dec1 = 0; sig2 = 0 ; dec2 = 0; } // 10^5
  187.             else
  188.             if(found_point == 1 && found_multiply == 0 && found_power == 1){ sig1 = 0; dec1 = 0; sig2 = 0 ; dec2 = 0; } // 10^5.1
  189.             else
  190.             if(found_point == 0 && found_multiply == 1 && found_power == 1){ dec1 = 0; dec2 = 0; sig2 = length - zeros - pow;}  // 3*10^5
  191.            
  192.             if( found_power == 1){
  193.                 // find out if scientiffic number is correctly written ; ok=0 -> ok=1
  194.                 // rule [1-9].[0-9]* x10^exp
  195.                 if( word[0] != '0' && word[1] == '.' ){ //  0.120*10^5 => 1.20*10^4
  196.                     ok = 1;
  197.                 }
  198.                 else
  199.                 {
  200.                     if( (word[0] == '-' || word[0] == '+' ) && word[1] != '0' && word[2] == '.' ){
  201.                         ok = 1; // -1.2*10^5
  202.                     }
  203.                     else
  204.                     {
  205.                         if( found_point == 0 && found_multiply == 1 ){
  206.                             if( word[1] == '*' ){ //4*10^5
  207.                                 ok = 1;
  208.                             }
  209.                             else
  210.                             {
  211.                                 if( (word[0] == '-' || word[0] == '+' ) && word[2] == '*'){ //-4*10^5
  212.                                     ok = 1;
  213.                                 }
  214.                             }
  215.                         }
  216.                     }
  217.                 }
  218.                 int len = strlen(exp);// reverse appended char array ... 123+ --> +321
  219.                 char exponent[len];
  220.                 int w = len - 1;
  221.                 for(i = 0 ; i < len ; i++){
  222.                     exponent[i] = exp[w];
  223.                     w--;
  224.                 }
  225.                 exponent[len] = '\0';
  226.                 if(base_start != 0){ // find the base ( default base = 10 )
  227.                     int c = 0;int s;
  228.                     if(base_end == 0){ // 10^5
  229.                         s = 0;
  230.                     }
  231.                     else
  232.                     {
  233.                         s = base_end + 1; // 1.25*10^5
  234.                     }
  235.                     char c_base[base_start - s]; // assign char array of correct size
  236.                     for(i = s ; i < base_start ; i++){
  237.                         c_base[c] = word[i];
  238.                         c++;
  239.                     }
  240.                     c_base[c] = '\0';
  241.                     fprintf(stdout,"%d,%d,%d,%d,%s,%s,%d\n",sig1,dec1,sig2,dec2,c_base,exponent,ok);
  242.                 }
  243.                 else
  244.                 { // base = 10 : used 4e+5
  245.                     fprintf(stdout,"%d,%d,%d,%d,10,%s,%d\n",sig1,dec1,sig2,dec2,exponent,ok);
  246.                 }
  247.             }
  248.             else
  249.             {   // no exponent : base = '1' exponent = '0'
  250.                 //several possible correct way of writing...
  251.                 if( ok == 0 && ( ( sig1 == sig2 + dec2 ) || ( sig1 + dec1 == sig2 + dec2 ) || ( dec1 == dec2 && sig2 == 1 ) )){ ok  = 1; }
  252.                 fprintf(stdout,"%d,%d,%d,%d,1,0,%d\n",sig1,dec1,sig2,dec2,ok);
  253.             }
  254.         }
  255.         cnt++;
  256.         input = argv[cnt];
  257.     }
  258.     return 0;
  259. }
  260.