Subversion Repositories wimsdev

Rev

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