home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c:16147 alt.sources:2415
- Newsgroups: comp.lang.c,alt.sources
- Path: sparky!uunet!cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!eff!world!tombaker
- From: tombaker@world.std.com (Tom A Baker)
- Subject: BINARY - Constants and conversions for base two.
- Message-ID: <BxBuo1.482@world.std.com>
- Keywords: C binary conversion
- Organization: Me, at The World Public Access UNIX, Brookline, MA
- Date: Sat, 7 Nov 1992 03:50:24 GMT
- Lines: 307
-
-
- A lot of very elegant code has been posted on this particular
- topic since that guy asked about it this week. I'm posting this
- because it has been useful to me. Of course, it is nowhere
- near as clean but ... it works, so what can I say?
-
- ---------------------------------------------------------------
- BINARY.H and BIN_RTNS.C
-
- As I said in my posting this morning, I recently had to do some
- fiddling with Forward Error Correction Codes; this meant
- reading and examining and writing bit patterns a lot. So
- I threw this stuff together.
-
- I know it's a quick-and-dirty thing, but it does the job. If
- you don't like it, fix it. My personal opionion is that binary
- is something that I use so seldom, that I'm not going to sink
- any more effort into it 'til I need it. Some of the more kludgy
- stuff is there to work with non-standard compilers.
-
- Okay.
-
- ---------------------------------------------------------------
-
- BINARY.H
-
- Place the '.h' file into a directory which your compiler can
- get to when it needs it. If you need binary constants, add the
- '#include "binary.h"' command to your program.
-
- The constants 'b0000' through 'b1111' are obvious. They're
- defined as (long) and they work pretty transparently.
-
- The way to use the B4(), B8(), ... B32() macros is also
- obvious, given the examples in the file 'testpgm.c' What
- is NOT obvious is the "trick" mentioned therein.
-
- In Ansi C, if I take the letter 'b' and the four digits
- "0101" and write 'b##0101', the preprocessor will
- concatenate that into the token 'b0101'. And you see that
- is defined as '(5)'.
-
- If you are using an older compiler, like a lot of Unix
- compilers, then edit the file so you take the letter 'b' and
- the four digits "0101" and write it as 'b/**/0101'. The
- older compilers will remove the comment, leaving 'b0101' and
- ... et cetera.
-
- ---------------------------------------------------------------
-
- BIN_RTNS.C
-
- Okay.
-
- long SBTOL(char *) - A string of the form "[0[b]][01]*" to
- integer. Strings might be "1", "b1111", or "0b11011011011".
-
- double SBTOD(char *) - Same thing, "[0[b]][01]*[.[01]*]", to
- double. Yes, you might want fractional binary. So "0b1.1"
- is one and a half, and "pi" is "11.0010010000111111011". See
- program "grope.c".
-
- char *bltos(long) - Convert any integer to a string. Yes, I use
- an intermediate, octal string. Yes, I use a static 100-byte
- buffer for it, and another static 300-byte buffer for the
- return value; when you've ported into yet another non-standard
- memory allocation library, you're content to use an array for
- small jobs. Anyway, this does work.
-
- ---------------------------------------------------------------
-
- pleasenoflames: If you want to roll your own, go ahead. I
- never said this was anything other than a useful quicky for
- me; I just have a nack for keeping my routines 'general' and
- therefore applicable to more than one situation.
-
- This software is released to the public domain. Please don't
- sell it for a million dollars profit without giving me some.
- I know where you live.
-
- If you improve this program, please send me a copy.
- tombaker@world.std.com || tabaker@aol.com || BIX as tombaker
- November 6, 1992
- ---------------------------------------------------------------
-
-
- Note: I took a cue from the preprocessor, which is supposed to
- do all arithmetic in (long) integers; all these constants
- are (long), and most times that will be transparent to
- (int) arithmetic. But the "testpgm.c" example shows a
- way to get mistakes if you aren't watchful.
-
- Note: This forces you to use four bits at a time, because it is all
- based on defining constants with four bits, named "b1001" and
- "b0000", for instance. If you want to implement the shorter
- names, from "b0" on up to "b111", go ahead (there are only 14
- of them). If you want to generate the macros for manipulating
- groups of three bits instead (if you think in octal), go ahead.
-
- Just don't go overboard; an earlier version did 8 bits, with
- 256 constants. That is a bit much for some preprocessors,
- considering how rarely any appreciable fraction of the constants
- are ever used.
-
- --------------------- CHAINSAW HERE ---------------------------
- /*- binary.h */
- /* 1992 - Thomas A. Baker. */
-
- #ifndef _BINARY_H_
- #define _BINARY_H_
-
- #define b0000 (0L)
- #define b0001 (1L)
- #define b0010 (2L)
- #define b0011 (3L)
- #define b0100 (4L)
- #define b0101 (5L)
- #define b0110 (6L)
- #define b0111 (7L)
- #define b1000 (8L)
- #define b1001 (9L)
- #define b1010 (10L)
- #define b1011 (11L)
- #define b1100 (12L)
- #define b1101 (13L)
- #define b1110 (14L)
- #define b1111 (15L)
-
- #define B4(a) ( b##a )
- /* Older compilers use the "comment trick". Get rid of the above line,
- then uncomment the following line and change the plusses to stars.
- #define B4(a) (b/++/a)
- */
-
- #define B8(a,i) (( B4(a) <<4L)|B4(i))
- #define B12(a,i,c) (( B8(a,i) <<4L)|B4(c))
- #define B16(a,i,c,d) ((B12(a,i,c) <<4L)|B4(d))
- #define B20(a,i,c,d,e) ((B16(a,i,c,d) <<4L)|B4(e))
- #define B24(a,i,c,d,e,f) ((B20(a,i,c,d,e) <<4L)|B4(f))
- #define B28(a,i,c,d,e,f,g) ((B24(a,i,c,d,e,f) <<4L)|B4(g))
- #define B32(a,i,c,d,e,f,g,h) ((B28(a,i,c,d,e,f,g)<<4L)|B4(h))
-
- long sbtol();
- double sbtod();
- char *bltos();
-
- #endif _BINARY_H_
- --------------------- CHAINSAW HERE ---------------------------
- /*- bin_rtns.c - Convert binary strings to and from numeric variables. */
- /* 1992 - Thomas A. Baker. */
-
- char buffer[101];
- char return_value[301];
-
- /*- long SBTOL(char *) - "[0[b]][01]*" to integer. */
- long
- sbtol(sb)
- char *sb;
- {
- long return_value = 0L;
-
- if( *sb != '\0' )
- {
- if( sb[0] == '0' && sb[1] == 'b' ) sb++;
- if( sb[0] == 'b') sb++;
-
- while( *sb && *sb>='0' && *sb<='1' )
- {
- return_value <<= 1;
- return_value += (long)(*sb & 1);
- sb++;
- }
- }
- return return_value;
- }
-
- /*- double SBTOD(char *) - "[0[b]][01]*[.[01]*]" to double. */
- double
- sbtod(sb)
- char *sb;
- {
- double return_value = (double) 0.0;
- double fraction = (double) 1.0;
-
- if( *sb != '\0' )
- {
- if( sb[0] == '0' && sb[1] == 'b' ) sb++;
- if( sb[0] == 'b') sb++;
-
- while( *sb>='0' && *sb<='1' )
- {
- return_value *= 2.0;
- return_value += (double)(*sb & 1);
- sb++;
- }
- if( *sb == '.' )
- {
- sb++;
- fraction = (double) 1.0;
- while( *sb>='0' && *sb<='1' )
- {
- fraction /= (double) 2.0;
- if( *sb & 1 )
- return_value += fraction;
- sb++;
- }
- }
- }
- return return_value;
- }
-
- /*- char *BLTOS(long) - Long to binary string. */
- char *
- bltos( b )
- long b;
- {
- char *p;
-
- sprintf( buffer, "%o", b );
- p = &buffer[0];
- strcpy( return_value, "" );
- while( *p=='0')
- p++;
- while( *p>='0' && *p<='7' )
- {
- if( *p & 4 )
- strcat( return_value, "1" );
- else
- strcat( return_value, "0" );
- if( *p & 2 )
- strcat( return_value, "1" );
- else
- strcat( return_value, "0" );
- if( *p & 1 )
- strcat( return_value, "1" );
- else
- strcat( return_value, "0" );
- p++;
- }
- p = &return_value[0];
- while( *p == '0' )
- p++;
- if( *p != '1' )
- {
- p = &return_value[0];
- strcpy( return_value, "0" );
- }
- return p;
- }
-
- #ifdef TESTING
- main()
- {
- long value;
- double fvalue;
- for(;;)
- {
- printf("L?");
- gets(buffer);
- value = sbtol(buffer);
- printf(" %ld\n", value);
- printf(" %s\n", bltos(value));
- printf("F?");
- gets(buffer);
- fvalue = sbtod(buffer);
- printf(" %lf\n", fvalue);
- value = (long) fvalue;
- printf(" %s\n", bltos(value));
- }
- }
- #endif TESTING
- --------------------- CHAINSAW HERE ---------------------------
- /*- testpgm.c */
- /* 1992 - Thomas A. Baker. */
-
- #include "binary.h"
-
- main()
- {
- printf("I'm %d years old.\n", B8(0010,0111) );
- printf("One 'K' is %d.\n", B12(0100,0000,0000) );
- printf("The year is %d.\n", B12(0111,1100,1000) );
- printf("Minus one is %d.\n", B16(1111,1111,1111,1111));
- printf("Minus one is %d.\n", B32(1111,1111,1111,1111,1111,1111,1111,1111));
- printf("Minus one is %ld.\n", B32(1111,1111,1111,1111,1111,1111,1111,1111));
- printf("-100,000 ISN'T %d.\n",B32(1111,1111,1111,1110,0111,1001,0110,0000));
- printf("-100,000 is %ld.\n",B32(1111,1111,1111,1110,0111,1001,0110,0000));
- return B4(0000);
- }
- --------------------- CHAINSAW HERE ---------------------------
- /*- grope.c */
- /* 1992 - Thomas A. Baker. */
-
- #include "binary.h"
-
- main()
- {
- char buffer[100];
-
- while(1)
- {
- gets(buffer);
- printf("%lf\n", sbtod(buffer));
- }
- }
- --------------------- CHAINSAW HERE ---------------------------
- End of Post
-