home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / c / 16147 < prev    next >
Encoding:
Text File  |  1992-11-08  |  9.3 KB  |  319 lines

  1. Xref: sparky comp.lang.c:16147 alt.sources:2415
  2. Newsgroups: comp.lang.c,alt.sources
  3. Path: sparky!uunet!cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!eff!world!tombaker
  4. From: tombaker@world.std.com (Tom A Baker)
  5. Subject: BINARY - Constants and conversions for base two.
  6. Message-ID: <BxBuo1.482@world.std.com>
  7. Keywords: C binary conversion
  8. Organization: Me, at The World Public Access UNIX, Brookline, MA
  9. Date: Sat, 7 Nov 1992 03:50:24 GMT
  10. Lines: 307
  11.  
  12.  
  13. A lot of very elegant code has been posted on this particular
  14. topic since that guy asked about it this week.  I'm posting this
  15. because it has been useful to me.  Of course, it is nowhere
  16. near as clean but ... it works, so what can I say?
  17.  
  18. ---------------------------------------------------------------
  19. BINARY.H and BIN_RTNS.C
  20.  
  21. As I said in my posting this morning, I recently had to do some
  22. fiddling with Forward Error Correction Codes; this meant
  23. reading and examining and writing bit patterns a lot.  So
  24. I threw this stuff together.
  25.  
  26. I know it's a quick-and-dirty thing, but it does the job.  If
  27. you don't like it, fix it.  My personal opionion is that binary 
  28. is something that I use so seldom, that I'm  not going to sink
  29. any more effort into it 'til I need it.  Some of the more kludgy
  30. stuff is there to work with non-standard compilers.
  31.  
  32. Okay.
  33.  
  34. ---------------------------------------------------------------
  35.  
  36.     BINARY.H
  37.  
  38. Place the '.h' file into a directory which your compiler can
  39. get to when it needs it.  If you need binary constants, add the
  40. '#include "binary.h"' command to your program.
  41.  
  42. The constants 'b0000' through 'b1111' are obvious.  They're
  43. defined as (long) and they work pretty transparently.
  44.  
  45. The way to use the B4(), B8(), ... B32() macros is also
  46. obvious, given the examples in the file 'testpgm.c'  What
  47. is NOT obvious is the "trick" mentioned therein.
  48.  
  49. In Ansi C, if I take the letter 'b' and the four digits
  50. "0101" and write 'b##0101', the preprocessor will
  51. concatenate that into the token 'b0101'.  And you see that
  52. is defined as '(5)'.
  53.  
  54. If you are using an older compiler, like a lot of Unix
  55. compilers, then edit the file so you take the letter 'b' and
  56. the four digits "0101" and write it as 'b/**/0101'.  The
  57. older compilers will remove the comment, leaving 'b0101' and
  58. ... et cetera.
  59.  
  60. ---------------------------------------------------------------
  61.  
  62.     BIN_RTNS.C
  63.  
  64. Okay.
  65.  
  66. long SBTOL(char *) - A string of the form "[0[b]][01]*" to
  67. integer.  Strings might be "1", "b1111", or "0b11011011011".
  68.  
  69. double SBTOD(char *) - Same thing, "[0[b]][01]*[.[01]*]", to
  70. double.  Yes, you might want fractional binary.  So "0b1.1"
  71. is one and a half, and "pi" is "11.0010010000111111011".  See
  72. program "grope.c".
  73.  
  74. char *bltos(long) - Convert any integer to a string.  Yes, I use
  75. an intermediate, octal string.  Yes, I use a static 100-byte
  76. buffer for it, and another static 300-byte buffer for the
  77. return value; when you've ported into yet another non-standard
  78. memory allocation library, you're content to use an array for
  79. small jobs.   Anyway, this does work.
  80.  
  81. ---------------------------------------------------------------
  82.  
  83. pleasenoflames: If you want to roll your own, go ahead.  I
  84. never said this was anything other than a useful quicky for
  85. me; I just have a nack for keeping my routines 'general' and
  86. therefore applicable to more than one situation.
  87.  
  88. This software is released to the public domain.  Please don't
  89. sell it for a million dollars profit without giving me some.
  90. I know where you live.
  91.  
  92. If you improve this program, please send me a copy.
  93. tombaker@world.std.com || tabaker@aol.com || BIX as tombaker  
  94. November 6, 1992
  95. ---------------------------------------------------------------
  96.  
  97.  
  98. Note:  I took a cue from the preprocessor, which is supposed to
  99.        do all arithmetic in (long) integers; all these constants
  100.        are (long), and most times that will be transparent to
  101.        (int) arithmetic.  But the "testpgm.c" example shows a
  102.        way to get mistakes if you aren't watchful.
  103.  
  104. Note: This forces you to use four bits at a time, because it is all
  105.       based on defining constants with four bits, named "b1001" and
  106.       "b0000", for instance.  If you want to implement the shorter
  107.       names, from "b0" on up to "b111", go ahead (there are only 14
  108.       of them).  If you want to generate the macros for manipulating
  109.       groups of three bits instead (if you think in octal), go ahead.
  110.  
  111.       Just don't go overboard; an earlier version did 8 bits, with
  112.       256 constants.  That is a bit much for some preprocessors,
  113.       considering how rarely any appreciable fraction of the constants
  114.       are ever used.
  115.  
  116. --------------------- CHAINSAW HERE ---------------------------
  117. /*- binary.h */
  118. /*  1992 - Thomas A. Baker. */
  119.  
  120. #ifndef _BINARY_H_
  121. #define _BINARY_H_
  122.  
  123. #define b0000 (0L)
  124. #define b0001 (1L)
  125. #define b0010 (2L)
  126. #define b0011 (3L)
  127. #define b0100 (4L)
  128. #define b0101 (5L)
  129. #define b0110 (6L)
  130. #define b0111 (7L)
  131. #define b1000 (8L)
  132. #define b1001 (9L)
  133. #define b1010 (10L)
  134. #define b1011 (11L)
  135. #define b1100 (12L)
  136. #define b1101 (13L)
  137. #define b1110 (14L)
  138. #define b1111 (15L)
  139.  
  140. #define  B4(a)               (  b##a                       )
  141. /* Older compilers use the "comment trick".  Get rid of the above line,
  142.    then uncomment the following line and change the plusses to stars.
  143.    #define B4(a) (b/++/a)
  144. */
  145.  
  146. #define  B8(a,i)             (( B4(a)            <<4L)|B4(i))
  147. #define B12(a,i,c)           (( B8(a,i)          <<4L)|B4(c))
  148. #define B16(a,i,c,d)         ((B12(a,i,c)        <<4L)|B4(d))
  149. #define B20(a,i,c,d,e)       ((B16(a,i,c,d)      <<4L)|B4(e))
  150. #define B24(a,i,c,d,e,f)     ((B20(a,i,c,d,e)    <<4L)|B4(f))
  151. #define B28(a,i,c,d,e,f,g)   ((B24(a,i,c,d,e,f)  <<4L)|B4(g))
  152. #define B32(a,i,c,d,e,f,g,h) ((B28(a,i,c,d,e,f,g)<<4L)|B4(h))
  153.  
  154. long   sbtol();
  155. double sbtod();
  156. char  *bltos();
  157.  
  158. #endif  _BINARY_H_
  159. --------------------- CHAINSAW HERE ---------------------------
  160. /*- bin_rtns.c - Convert binary strings to and from numeric variables. */
  161. /*  1992 - Thomas A. Baker. */
  162.  
  163. char buffer[101];
  164. char return_value[301];
  165.  
  166. /*-   long SBTOL(char *) - "[0[b]][01]*" to integer. */
  167. long
  168. sbtol(sb)
  169. char *sb;
  170. {
  171.     long return_value = 0L;
  172.  
  173.     if( *sb != '\0' )
  174.     {
  175.         if( sb[0] == '0' && sb[1] == 'b' ) sb++;
  176.         if( sb[0] == 'b')                  sb++;
  177.  
  178.         while( *sb && *sb>='0' && *sb<='1' )
  179.         {
  180.             return_value <<= 1;
  181.             return_value  += (long)(*sb & 1);
  182.             sb++;
  183.         }
  184.     }
  185.     return return_value;
  186. }
  187.  
  188. /*-   double SBTOD(char *) - "[0[b]][01]*[.[01]*]" to double. */
  189. double
  190. sbtod(sb)
  191. char *sb;
  192. {
  193.     double return_value = (double) 0.0;
  194.     double fraction     = (double) 1.0;
  195.  
  196.     if( *sb != '\0' )
  197.     {
  198.         if( sb[0] == '0' && sb[1] == 'b' ) sb++;
  199.         if( sb[0] == 'b')                  sb++;
  200.  
  201.         while( *sb>='0' && *sb<='1' )
  202.         {
  203.             return_value *= 2.0;
  204.             return_value += (double)(*sb & 1);
  205.             sb++;
  206.         }
  207.         if( *sb == '.' )
  208.         {
  209.             sb++;
  210.             fraction = (double) 1.0;
  211.             while( *sb>='0' && *sb<='1' )
  212.             {
  213.                 fraction /= (double) 2.0;
  214.                 if( *sb & 1 )
  215.                     return_value += fraction;
  216.                 sb++;
  217.             }
  218.         }
  219.     }
  220.     return return_value;
  221. }
  222.  
  223. /*-   char *BLTOS(long) - Long to binary string. */
  224. char *
  225. bltos( b )
  226. long  b;
  227. {
  228.     char *p;
  229.  
  230.     sprintf( buffer, "%o", b );
  231.     p = &buffer[0];
  232.     strcpy( return_value, "" );
  233.     while( *p=='0')
  234.         p++;
  235.     while( *p>='0' && *p<='7' )
  236.     {
  237.         if( *p & 4 )
  238.             strcat( return_value, "1" );
  239.         else
  240.             strcat( return_value, "0" );
  241.         if( *p & 2 )
  242.             strcat( return_value, "1" );
  243.         else
  244.             strcat( return_value, "0" );
  245.         if( *p & 1 )
  246.             strcat( return_value, "1" );
  247.         else
  248.             strcat( return_value, "0" );
  249.         p++;
  250.     }
  251.     p = &return_value[0];
  252.     while( *p == '0' )
  253.         p++;
  254.     if( *p != '1' )
  255.     {
  256.         p = &return_value[0];
  257.         strcpy( return_value, "0" );
  258.     }
  259.     return p;
  260. }
  261.  
  262. #ifdef TESTING
  263. main()
  264. {
  265.     long value;
  266.     double fvalue;
  267.     for(;;)
  268.     {
  269.         printf("L?");
  270.         gets(buffer);
  271.         value = sbtol(buffer);
  272.         printf("          %ld\n", value);
  273.         printf("          %s\n",  bltos(value));
  274.         printf("F?");
  275.         gets(buffer);
  276.         fvalue = sbtod(buffer);
  277.         printf("          %lf\n", fvalue);
  278.         value = (long) fvalue;
  279.         printf("          %s\n",  bltos(value));
  280.     }
  281. }
  282. #endif TESTING
  283. --------------------- CHAINSAW HERE ---------------------------
  284. /*- testpgm.c */
  285. /*  1992 - Thomas A. Baker. */
  286.  
  287. #include "binary.h"
  288.  
  289. main()
  290. {
  291.   printf("I'm %d years old.\n",  B8(0010,0111) );
  292.   printf("One 'K' is %d.\n",    B12(0100,0000,0000) );
  293.   printf("The year is %d.\n",   B12(0111,1100,1000) );
  294.   printf("Minus one is %d.\n",  B16(1111,1111,1111,1111));
  295.   printf("Minus one is %d.\n",  B32(1111,1111,1111,1111,1111,1111,1111,1111));
  296.   printf("Minus one is %ld.\n", B32(1111,1111,1111,1111,1111,1111,1111,1111));
  297.   printf("-100,000 ISN'T %d.\n",B32(1111,1111,1111,1110,0111,1001,0110,0000));
  298.   printf("-100,000  is  %ld.\n",B32(1111,1111,1111,1110,0111,1001,0110,0000));
  299.   return B4(0000);
  300. }
  301. --------------------- CHAINSAW HERE ---------------------------
  302. /*- grope.c */
  303. /*  1992 - Thomas A. Baker. */
  304.  
  305. #include "binary.h"
  306.  
  307. main()
  308. {
  309.     char buffer[100];
  310.  
  311.     while(1)
  312.     {
  313.         gets(buffer);
  314.         printf("%lf\n", sbtod(buffer));
  315.     }
  316. }
  317. --------------------- CHAINSAW HERE ---------------------------
  318. End of Post
  319.