Subversion Repositories wimsdev

Rev

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