Number to bit vector


 
Thread Tools Search this Thread
Top Forums Programming Number to bit vector
# 8  
Old 02-29-2016
Actually no, although I should have asked.
Please give me an example?!
Thanks!
# 9  
Old 03-10-2016
As long as you are converting unsigned integral values that fit into an integral type supported by your compiler, using something similar to what migurus suggested in post #2 in this thread will be much faster. If you are trying to convert arbitrarily large values, bc is your friend. For example, suppose we have the bc script:
Code:
/*
** Invoke this script using: 
**	bc -l binary_print.bc
**
** In addition to the math library laoded by the -l option, this file defines a
** function:
**	f(b, expression)
** The first argument ("b") is a decimal integer specifyting the number of
** binary digits to produce as output and the 2nd argument ("expressioun") is a
** string that will be interpreted as an arithmetic expression that should
** yield a non-negative decimal integer value ("v").  The function will attempt
** to convert that decimal value into a "b" bit binary number.  If successful,
** f(b,expression) will write a string to standard output using the format:
**      RESULT: <bbb>
** where <bbb> is "b" binary digits having the same numeric value as the
** decimal integer "v".  If "v" is negative or if "v" can't be represented by
** an unsigned "b" binary digit number, a diagnost message will be written to
** standard output using the format:
**      ERROR: <diagnostic message>: <ddd>
** where <diagnostic message> is a string indicating the problem and <ddd> is
** the decimal value resulting from the interpretation of <expression>.
**
** Note that if a number to be printed (not counting leading zeros) consists of
** more than 67 digits, bc will split the output onto multiple lines with all
** but the last line ending with a backslash character ("\") just before the
** <newline> character at the end of the line.  So, for example the call
** f(2,10^69-1) will produce the output:
ERROR: Overflow: 99999999999999999999999999999999999999999999999999999999999999999999\
9
** and the call f(70,2^68) will produce the output:
f(70,2^68)
RESULT: 010000000000000000000000000000000000000000000000000000000000000000000\
0
** so any application reading output from bc needs to be prepared to combine
** lines by stripping <backslash><newline> character pairs.
**
** Some implementations of bc allow multi-character function names and much
** better ouptut formatting capabilities; this script only uses features that
** are required to be provided by the POSIX standards.
*/

/*
** Reduce chance of truncation and rounding errors in calculation of l(v)/l(2)
** for large b values by increasing the # of digits used in the calculations to
** 50 digits after the decimal point.
*/
scale=50

/* Define the function... */
define f(b, v){
	obase=A
	if(v >= 2^b) {"ERROR: Overflow: ";return(v)}
	if(v<0) {"ERROR: Negative value: "; return(v)}
	if(v>0) n=l(v)/l(2)
	if(v<=0) {v=0;n=0}
	obase=2
	"RESULT: "
	for(i=b;i-n>1;i--){"0"}
	return(v)
}

If we directly invoke bc using:
Code:
bc -l binary_print.bc

to start bc with its math library and the above file loaded, it will then read commands from standard input. So we can have an interactive session as shown here (this is with the bc utility included with OS X El Capitan Release 10.11.3):
Code:
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
f(5,31)
RESULT: 11111
f(5,32)
ERROR: Overflow: 32
f(5,31+)
(standard_in) 3: parse error
f(5,-1)
ERROR: Negative value: -1
f(240,999999999999999999999999999999999999999999999999999999999999999999999999)
RESULT: 10010000111001000000111110111110111010100001110100111010010010101011\
11001000100101010101111010010100011011111110001100011100110111001111\
01100110111101100011010011100000111111111111111111111111111111111111\
111111111111111111111111111111111111
f(2,999999999999999999999999999999999999999999999999999999999999999999999999)
ERROR: Overflow: 99999999999999999999999999999999999999999999999999999999999999999999\
9999

(where the text shown in bold was typed by me and the other text was produced by bc). The Free Software Foundation copyright notice is only displayed when stdout is connected to a terminal device file (so if you pipe this output into another process, you don't have to worry about skipping over that text. Not that "long" numbers are split by bc into multiple lines when then are printed with all but the last line terminated by a <backslash> immediately preceding the <newline> line terminator. (Note also that the f(bits, value) function in the above file does not make any attempt to split long strings of leading zeros, so if you print a small value with a large number of bits requested, you can get much longer lines.

If you just wanted to print various numbers using the bc f() function defined in the above file, you could write a C program using system() or popen() to invoke bc with the above script. But, if you want a C subroutine to be able to send commands interactively to bc running the above script and read the responses the script produces, you could use something like:
Code:
#define BINARY_PRINT_PATH	"/Users/dwc/test/unix.com/C/Number_to_bit_vector/binary_print.bc"
#define BUFSIZE			32768

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

FILE	*stream_from_bc,	// STDIO stream from bc utility
	*stream_to_bc;		// STDIO stream to bc utility
char	buf[BUFSIZE];		// Buffer to hold a line read from bc

// join_print() -- join continuation lines and print
int join_print(
	FILE	*restrict out_stream,	// output stream
	const	char *restrict string,	// string to print before joined lines
					// from buf
	size_t	offset) {		// offset from base of buf to start of
					// 1st part of output to be printed by
					// the "%s" in format

	// Print the following to the stream named by <out_stream>:
	//  1.	the given <string> operand,
	//  2.	the string starting at buf[<offset>] up to but not including a
	//	'\\' immediately followed by a '\n' at the end of the string,
	//  3.	if, and only if, a "\\\n" is found at the end of a line, read
	//	another line from stream_from_bc into buf and repeat steps 2
	//	and 3 until a line has been read and printed that does not end
	//	with "\\\n".
	// On successful completion, this function returns the number of bytes
	// written to <out_stream>; otherwise it returns -1 and sets errno to
	// indicate the error.
	// NOTE:  Error checking is grossly inadequate in this subroutine.
	// Adding reasonable error checking is left as an exercise for the
	// reader.

	size_t	len = strlen(buf);// length of string in buf[]
	int	off = offset,	  // current input offset from the base of buf[]
		rc,		  // hold area for accumalted return code value
		ret,		  // return code hold area
		serrno;		  // saved errno value
	
	if((rc = fprintf(out_stream, "%s", string)) < 0)
		return(rc);
	// XXX Should check for incomplete line in buf[].
	while(strcmp("\\\n", buf + len - 2) == 0) {
		buf[len - 2] = '\0';
		ret = fprintf(out_stream, "%s", buf + off);
		// XXX Should check for fprintf() failure.
		rc += ret;
		(void)fgets(buf, sizeof(buf), stream_from_bc);
		// XXX Should check for fgets() failure.
		off = 0;
		len = strlen(buf);
	}
	ret = fprintf(out_stream, "%s", buf + off);
	// XXX Should check for fprintf() failure.
	rc += ret;
	return(rc);
}

// start_bc() -- For a child and exec bc
void start_bc() {
	// Create a child to run bc and connect a STDIO stream from the calling
	// process to its standard input and another STDIO stream from bc's
	// standard output back to the calling process.

	int	pipe_from_bc[2],// File descriptors for pipe from bc utility.
		pipe_to_bc[2];	// File descriptors for pipe to bc utility.
	pid_t	pid;		// Process ID of child.

	// Set up two pipes to communicate with the bc command we will fork and
	// exec.
	if(pipe(pipe_from_bc)) {
		perror("pipe(pipe from bc) failed");
		exit(1);
	}
	if(pipe(pipe_to_bc)) {
		perror("pipe(pipe to bc) failed");
		exit(2);
	}

	// Fork a child to run bc.
	if((pid = fork()) == -1) {
		// fork() failed.
		perror("fork() failed");
		exit(3);
	} else if(pid == 0) {
		// We are in the child.
		// Rearrange file descriptors so this process's STDIN is the
		// read end of pipe_to_bc, and STDERR and STDOUT is the write
		// end of pipe_from_bc.
		(void)close(0);
		(void)close(1);
		(void)close(2);
		(void)dup(pipe_to_bc[0]);
		(void)dup(pipe_from_bc[1]);
		(void)dup(pipe_from_bc[1]);
		(void)close(pipe_to_bc[0]);
		(void)close(pipe_to_bc[1]);
		(void)close(pipe_from_bc[0]);
		(void)close(pipe_from_bc[1]);

		// Overlay this process with bc.
		execlp("bc", "bc", "-l", BINARY_PRINT_PATH, NULL);
		
		// There is no return from a successful execlp() call...
		perror("execlp(bc) failed");
		exit(4);
	}

	// We are in the parent and the child created to run bc is running..
	// Close file descriptors that are not needed in the parent and set up
	// line buffered STDIO streams on the file descriptors set up to write
	// commands to bc and to read results from bc.
	(void)close(pipe_to_bc[0]);
	(void)close(pipe_from_bc[1]);
	if((stream_to_bc = fdopen(pipe_to_bc[1], "w")) == NULL) {
		perror("fdopen(stream to bc) failed");
		exit(5);
	}
	if((stream_from_bc = fdopen(pipe_from_bc[0], "r")) == NULL) {
		perror("fdopen(stream from bc) failed");
		exit(6);
	}
	if(setvbuf(stream_to_bc, NULL, _IOLBF, BUFSIZ)) {
		perror("setvbuf(stream to bc) failed");
		exit(7);
	}
	if(setvbuf(stream_from_bc, NULL, _IOLBF, BUFSIZ)) {
		perror("setvbuf(stream from bc) failed");
		exit(8);
	}
}

int main(int argc, char *argv[]) {
	char	err[] = "ERROR:",	// Start of bc script error message
		result[] = "RESULT:";	// Start of bc script success message
	int	bits[] = {16, 64, 240},	// bits to print in binary values
		i,			// loop counter
		j;			// loop counter

	// Fork a child to run bc.
	start_bc();

	// At this point we have a child process running bc with the math
	// library loaded and with the function f(b,v) loaded from the file
	// binary_print.bc.  See binary_print.bc for the behavior of the
	// function f() and for the output formats produced.

	// Send f() function calls to bc and read and print the results...
	for(i = 1; i < argc; i++) {
		for(j = 0; j < sizeof(bits)/sizeof(bits[0]); j++) {
			// NOTE: Following calls to printf(), fprintf(), and
			// join_print() should check for errors instead of
			// casting result to void.  Fixing this and improviing
			// error checking in join_print() are left as an
			// exercise for the reader.
			(void)printf("Requesting %d-bit representation of %s\n",
			    bits[j], argv[i]);
			(void)fprintf(stream_to_bc, "f(%d,%s)\n", bits[j],
			    argv[i]);
			if(fgets(buf, sizeof(buf), stream_from_bc) != buf) {
				if(feof(stream_from_bc))
					fprintf(stderr,
					    "Unexpected EOF from bc.\n");
				else	perror("fgets(stream from bc) failed");
				exit(9);
			}
			if(!strncmp(buf, result, sizeof(result) - 1)) {
				// Succesful conversion, print results.
				(void)join_print(stdout, "", sizeof(result));
			} else if(!strncmp(buf, err, sizeof(err) - 1)) {
				// f() function call error, print diagnostic.
				(void)join_print(stderr, "Conversion error: ",
				    sizeof(err));
			} else {// other bc detected error, print diagnostic.
				(void)join_print(stderr, "bc syntax error: ",
				    0);
			}
		}
		putchar('\n');
	}
}

Since we are writing data to bc through a pipe and reading data from bc from a pipe, popen() and system() won't really do what we want. So this uses fork() and execlp() to start bc and uses pipe(), close(), and dup(), and fdopen() to connect two pipes between the parent and child connecting the read end of one pipe to the standard input of bc and the write end of the other pipe to the standard output and standard error output of bc. When the parent reads data from bc it throws away <backslash><newline> character pairs while copying the results to the parent's standard output. Note that you'll have to change the pathname defined by the macro BINARY_PRINT_PATH to specify an absolute pathname specifying where you placed the bc script above on your system. If you save the above C code in a file named tester.c and build it using:
Code:
make tester

and invoke it with something like:
Code:
./tester 1 65535 65536 999999999999999999999999999999999999999999999999999999999
999999999999999 1208925819614629174706175

producing the output (as viewed on an 80 column wide terminal with line wrapping enabled [to avoid 240 character wide displays in this post]):
Code:
Requesting 16-bit representation of 1
0000000000000001
Requesting 64-bit representation of 1
0000000000000000000000000000000000000000000000000000000000000001
Requesting 240-bit representation of 1
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000001

Requesting 16-bit representation of 65535
1111111111111111
Requesting 64-bit representation of 65535
0000000000000000000000000000000000000000000000001111111111111111
Requesting 240-bit representation of 65535
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000001111111111111111

Requesting 16-bit representation of 65536
Conversion error: Overflow: 65536
Requesting 64-bit representation of 65536
0000000000000000000000000000000000000000000000010000000000000000
Requesting 240-bit representation of 65536
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000010000000000000000

Requesting 16-bit representation of 99999999999999999999999999999999999999999999
9999999999999999999999999999
Conversion error: Overflow: 9999999999999999999999999999999999999999999999999999
99999999999999999999
Requesting 64-bit representation of 99999999999999999999999999999999999999999999
9999999999999999999999999999
Conversion error: Overflow: 9999999999999999999999999999999999999999999999999999
99999999999999999999
Requesting 240-bit representation of 9999999999999999999999999999999999999999999
99999999999999999999999999999
10010000111001000000111110111110111010100001110100111010010010101011110010001001
01010101111010010100011011111110001100011100110111001111011001101111011000110100
11100000111111111111111111111111111111111111111111111111111111111111111111111111

Requesting 16-bit representation of 1208925819614629174706175
Conversion error: Overflow: 1208925819614629174706175
Requesting 64-bit representation of 1208925819614629174706175
Conversion error: Overflow: 1208925819614629174706175
Requesting 240-bit representation of 1208925819614629174706175
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
11111111111111111111111111111111111111111111111111111111111111111111111111111111

I assume that instead of printing the binary values, you'll want to set up an internal array containing bits or bytes containing the values reported by bc, but I hope you'll be able to use this as a guide for what needs to be done to communicate with a child process and show you how you can modify string output from one process to get a desired output format.

Last edited by Don Cragun; 03-10-2016 at 06:13 AM.. Reason: Fix typos.
This User Gave Thanks to Don Cragun For This Post:
# 10  
Old 03-10-2016
Thanks Don!
Your reply overwhelmed me to death! As usual, this is way more than I needed.
BTW, how long does it take for a regular CS graduate to get the level like this with C?
# 11  
Old 03-10-2016
Quote:
Originally Posted by yifangt
Thanks Don!
Your reply overwhelmed me to death! As usual, this is way more than I needed.
BTW, how long does it take for a regular CS graduate to get the level like this with C?
I'm glad that my code helped, but there isn't anything overwhelming in what I did. Start at the beginning and decide what you want to do. Then build the pieces you need to get there one by one until you have something that works. If you run into a problem with one of the pieces fitting in after you have started working on another piece, don't be afraid to throw one or both of them away and redo it/them a different way that fits in better.

I have no idea what a regular CS graduate now days knows about C, nor how long it takes one to be able to read, understand, nor write a program like this. But, a few decades of fixing bugs in other people's code, writing my own code, and writing and maintaining the standards that specify the behavior of the POSIX-specified utilities and C interfaces certainly helps. The key point is that practicing programming helps. Smilie

When I was a CS grad, I knew FORTRAN and three different assembler languages and a couple of FORTRAN high precision math libraries. I picked up Algol, COBOL, Lisp, and PL/1 in a comparative programming languages course one semester while working on my Masters in computer engineering. (I used to have decks of cards in Algol, COBOL, Fortran, Lisp, and PL/1 that could read in a number expressed as Roman numerals, multiply it by two and add seven, and write out the result as Roman numerals. I won't say that I mastered COBOL, Lisp, and PL/1 in those thirteen weeks; but I learned how to read a manual and how to experiment with code.) After college, I was able to learn a few other programming languages in about a week of concentrated study as long as I had easy access to a compiler for that language, a good manual for that language, and no distractions. Note, however, that I have never claimed to be normal nor regular.
This User Gave Thanks to Don Cragun For This Post:
# 12  
Old 03-10-2016
"......a few decades of...... No wonder your reply is always like that!!!
Thanks a lot!
Login or Register to Ask a Question

Previous Thread | Next Thread

6 More Discussions You Might Find Interesting

1. Windows & DOS: Issues & Discussions

Which version of Windows Vista to install with a product key? 32-bit or 64-bit?

Hello everyone. I bought a dell laptop (XPS M1330) online which came without a hard drive. There is a Windows Vista Ultimate OEMAct sticker with product key at the bottom case. I checked dell website (here) for this model and it says this model supports both 32 and 64-bit version of Windows... (4 Replies)
Discussion started by: milhan
4 Replies

2. Programming

How bit representation of a number can be done in c?

I have an assignment in which a character is the input of which some bits(from a position to certain position) are to be inverted (1's complement) and then the resultant character is to be returned....for example unsigned char x = J from p = 3 to offset n = 5 01001010 inverted to... (1 Reply)
Discussion started by: ezee
1 Replies

3. Shell Programming and Scripting

How to handle 64 bit arithmetic operation at 32 bit compiled perl interpreter?H

Hi, Here is the issue. From the program snippet I have Base: 0x1800000000, Size: 0x3FFE7FFFFFFFF which are of 40 and 56 bits. SO I used use bignum to do the math but summing them up I always failed having correct result. perl interpreter info, perl, v5.8.8 built for... (0 Replies)
Discussion started by: rrd1986
0 Replies

4. Programming

Help with bit vector and setting its bits?

void shuffle (card_t cards, card_t cards2, char *bitvec) { int i; unsigned char temp, r; srand(time(NULL)); for (i = 0; i < 52; i++) { r = rand() % 52; temp = bitvec; if (!(temp & (1 << (8- (r % 8))))) { temp |= (1 << (8- (r % 8)));------->is this my problem? } } } ok so I am... (1 Reply)
Discussion started by: bjhum33
1 Replies

5. Shell Programming and Scripting

Help needed in converting number to bit

Hi, I have the following file input:- 542 4795 61 543 4795 61 544 0 0 545 292 ... (5 Replies)
Discussion started by: ahjiefreak
5 Replies

6. Programming

copying or concatinating string from 1st bit, leaving 0th bit

Hello, If i have 2 strings str1 and str2, i would like to copy/concatenate str2 to str1, from 1st bit leaving the 0th bit. How do i do it? (2 Replies)
Discussion started by: jazz
2 Replies
Login or Register to Ask a Question