I'm working on an embedded systems project where I'm trying to demodulate data from an IR sensor (which uses 'pulse width modulation'). The code below simply waits for the IR Sensor to start pulsing, and then measure the width (duration) of each high and low pulse.
In this code, I have a loop where I'm incrementing an integer:
irPulseSet irReadPulse()
{
irPulseSet outputPulseSet;
int pulseCount = 0;
int finished = 0;
while(1)
{
int lowPulse = 0;
int highPulse = 0;
while( bit_is_clear( irSensorPin , irSensorPinNo ) )
{
highPulse++;
_delay_us( 20 );
}
while( !bit_is_clear( irSensorPin , irSensorPinNo ) )
{
if ( lowPulse > 3250 )
{
finished = 1;
break;
}
lowPulse++;
_delay_us( 20 );
}
if ( finished )
break;
outputPulseSet.pulses[pulseCount][0] = highPulse * 20;
outputPulseSet.pulses[pulseCount][1] = lowPulse * 20;
pulseCount++;
}
// Assign pulse count to output pulse set
outputPulseSet.pulseCount = pulseCount;
return outputPulseSet;
}
Because this is an embedded systems project, and my resources are limited, I'm doing my debugging with an LCD display (as the circuit cannot be connected to a computer)
Printing each pulse
int irPrintPulses( irPulseSet pulseSet )
{
int counter;
for( counter = 0; counter <= pulseSet.pulseCount; counter++ )
{
LCDClearScreen();
char printStr[100];
sprintf( printStr , "H%iL%i;%i " , pulseSet.pulses[counter][0] , pulseSet.pulses[counter][1] , counter );
LCDSendString( printStr );
_delay_ms(1000);
}
_delay_ms(5000);
LCDClearScreen();
LCDSendString( "Finished pulse print!" );
_delay_ms(1000);
LCDClearScreen();
return 0;
}
The lowPulse int seems to sometimes be negative (eg value of -1054). I'm totally puzzled as it's first defined as 0 and all I ever do to it is increment it, so how can it become negative?
You have X bits to represent a number: 1 bit is for the signal and X - 1 bits is for the value
lets say you have a number that is represented with 4 bits:
0000 = 0
0001 = 1
...
0111 = 7
If you increment 1 here, you will change the first bit (the signal bit)
1000 = -8
Try the code bellow
#include <stdio.h>
#include <limits.h>
int main()
{
int i = INT_MAX;
printf("%d\n", i);
printf("%d\n", i + 1);
printf("%u\n", i + 1);
if(i > 0)
printf("greater\n");
i++;
if(i < 0)
printf("what kind of witchcraft is that?");
}
Once you add one after the maximum value it will flip to the maximum negative value, the 3rd printf is printing as an unsigned value (using the 1st bit not for the signal but for value)...
Since this is embedded I am going to assume that you are working with 16 bit integers. As a result, if you increment highPulse 32,768 times it will overflow and become negative. The value transitions from 0x7fff (positive) to 0x8000 (negative).
Given a delay loop of 20 usec, this will take 655.36 msec. Any time the first loop has to wait for this long for the bit to transition you will get negative numbers. I would have thought this is quite possible.
Do you have 32 bit longs? If so, the simplest solution is probably to use them for these counters. Then it will take about 40,000 seconds to overflow, which should be enough.
Related
I have a binary number, stored in an array of bytes (unsigned chars), and want to turn it into a decimal string.
The "obvious" approach that i found online was, to iterate over the array, add everything up while keeping track of the base and then converting it into a string but this doesn't work for me because the whole number doesn't fit into any common datatype and therefor cannot be added up in one go.
typedef unsigned char byte;
typedef struct Bin {
int size;
byte *ptrToVal;
} Bin;
void asDecString(Bin* this) {
signed int n = 0;
for(int i = 0; i < this->size; i++) {
n += this->ptrToVal[i] << (i * 8);
printf("%u\t%u\t%u\n", this->ptrToVal[i], n, i);
}
printf("%u\n", n);
}
The second, slow approach is to store the number in a string and multiply the digits in the string.
I'm looking for a quick way to implement this in c, but because I'm completely new to the language I don't know the features that well.
Out of curiosity and interest, here's my implementation of the algorithm found at:
https://my.eng.utah.edu/~nmcdonal/Tutorials/BCDTutorial/BCDConversion.html
It outputs intermediary values as each bit is processed. The verbose block can be moved out of the loop after testing.
Try it with one or two 'hex' bytes to begin with.
#include <stdio.h>
typedef unsigned char binByte;
void toBCD( binByte *p, int size ) {
const int decSize = 50; // Arbitrary limit of 10^49.
binByte decDgt[ decSize ]; // decimal digits as binary 'nibbles'.
int curPow10 = 0;
memset( decDgt, 0, sizeof(decDgt) );
for( int i = 0; i < size; i++ ) {
binByte oneByte = p[ i ]; // Initial one byte value
for( binByte bit = 0x80; bit > 0; bit >>= 1 ) {
for( int ii = 0; ii <= curPow10; ii++ )
if( decDgt[ ii ] >= 5 ) // Algorithm step
decDgt[ ii ] += 3;
for( ii = curPow10; ii >= 0; ii-- ) {
decDgt[ ii ] <<= 1;
if( decDgt[ ii ] & 0x10 ) { // Carry high bit?
decDgt[ ii + 1 ] |= 0x1;
if( ii == curPow10 ) // new power of 10?
curPow10++;
}
decDgt[ ii ] &= 0xF; // dealing in 'nibbles'
}
decDgt[ 0 ] |= ( (oneByte & bit) != 0 ); // truth value 0 or 1
printf( "Bottom: " );
for( ii = curPow10; ii >= 0; ii-- )
putchar( decDgt[ ii ] + '0' );
putchar( '\n' );
}
}
}
void main( void ) {
binByte x[] = { 0x01, 0xFF, 0xFF, 0xFF, 0xFF };
toBCD( x, sizeof(x) );
}
For large integers; you want to break them into "small enough integers", then convert the "small enough integers" into digits.
For example, lets say you have the number 1234567890. By doing next_piece = number / 100; number = number % 100; you could split it into pieces that fit in one byte, then print the smaller pieces 12, 34, 56, 78, 90 (with nothing between them and leading zeros to ensure the piece 03 doesn't get printed as 3) so that it looks like a single larger number.
In the same way you could split it into pieces that fit in a 32-bit unsigned integer; so that each piece is from 0 to 1000000000, by doing something like next_piece = number / 1000000000; number = number % 1000000000;. For example, the number 11223344556677889900112233445566778899 could be split into 11, 223344556, 677889900, 112233445, 566778899 and then printed (with leading zeros, etc).
Of course for big integers you'd need to implement a "divide by 1000000000" that works with your data structure, that returns a uint32_t (the remainder or the next piece) and the original value divided by 1000000000.
This is where things get messy. Using an array of bytes is slow, and signed numbers are painful. To fix that you'd want something more like:
#include <stdint.h>
typedef struct AlternativeBin {
int signFlag;
int size;
uint32_t *ptrToVal;
} AlternativeBin;
It wouldn't be hard to convert from your original format into this alternative format (if you can't just use this alternative format for everything).
The division loop would look something like (untested):
// WARNING: Destructive (the input value is used to return the quotient)
uint32_t getNextPiece(AlternativeBin * value) {
uint64_t temp = 0;
int i;
// Do the division
for(i = value->size - 1; i >= 0; i--) {
temp = (temp << 32) | value->ptrToVal[i];
value->ptrToVal[i] = temp / 1000000000ULL;
temp = temp % 1000000000ULL;
}
// Reduce the size of the array to improve performance next time
while( (value->size > 0) && (value->ptrToVal[value->size - 1] == 0) ) {
value->size--;
}
return temp;
}
..which means the "printing loop" (using recursion to reverse the order of pieces) might look like (untested):
#include <stdio.h>
#include <inttypes.h>
// WARNING: Recursive and destructive (the input value is destroyed)
void printPieces(AlternativeBin * value) {
uint32_t piece;
piece = getNextPiece(value);
if( !value_became_zero(value) ) {
printPieces(value);
printf("%09" PRIu32, piece); // Print it with leading zeros
} else {
printf("%" PRIu32, piece); // No leading zeros on first piece printed
}
}
The other minor inconvenience is that you'll want to print a '-' at the start if the value is negative (untested):
// WARNING: Destructive (the input value is destroyed)
void printValue(AlternativeBin * value) {
if(value->signFlag) {
printf("-");
}
printPieces(value);
}
If you wanted you could also create a copy of the original data here (get rid of the WARNING: Destructive comment by destroying a copy and leaving the original unmodified); and convert from your original structure (bytes) into the alternative structure (with uint32_t).
Note that it would be possible to do all of this with bytes (something like your original structure) using a divisor of 100 (instead of 1000000000). It'd just be a lot slower because the expensive getNextPiece() function will need to be called about 4.5 as many times.
I was trying to understand the meanings and rules of this code which is humidity and temperture module.
I want run it with C and RaspberryPi.
However even though I tried to figure this out, I don't understand what ***** part is doing.
Why MAXTIMINGS is 85?
Why if sentence compare to 255?
Could you tell me someone what the meaning of **** part is?
Here is a timing chart and datasheet link.
(https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf#search='DHT11+datasheet')
enter image description here
#include <stdio.h>
#include <wiringPi.h>
#define MAXTIMINGS 85
#define DHTPIN 15 //DHT connect to TxD
int dht11_dat[5] ={0,0,0,0,0};//store DHT11 data
void read_dht11_dat()
{
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0,i;
float f;//fahrenheit
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
//pull pin down to send start signal
pinMode( DHTPIN, OUTPUT );
digitalWrite( DHTPIN, LOW );
delay( 18 );
//pull pin up and wait for sensor response
digitalWrite( DHTPIN, HIGH );
delayMicroseconds( 40 );
//prepare to read the pin
pinMode( DHTPIN, INPUT );
***************************************************************
//detect change and read data
for ( i = 0; i < MAXTIMINGS; i++ ) {
counter = 0;
while ( digitalRead( DHTPIN ) == laststate ) {
counter++;
delayMicroseconds( 1 );
if ( counter == 255 ) { break; }
}
laststate = digitalRead( DHTPIN );
if ( counter == 255 ) break;
//ignore first 3 transitions if ( (i >= 4) && (i % 2 == 0) )
{
//shove each bit into the storage bytes
dht11_dat[j / 8] <<= 1;
if ( counter > 16 )dht11_dat[j / 8] |= 1;
j++;
}
}
**************************************************************************
//check we read 40 bits(8bit x 5) +verify checksum in the last byte
//print it out if data is good
if ( (j >= 40) &&
(dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
{
f = dht11_dat[2] * 9. / 5. + 32;
printf( "Humidity = %d.%d %% Temperature = %d.%d C (%.1f F)\n",
dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
}
else
{
printf( "Data not good, skip\n" );
}
}
int main( void )
{
if ( wiringPiSetup() == -1 )
{
fprintf(stderr,"Can't init wiringPi: %s\n",strerror(errno));
exit(EXIT_FAILURE);
}
print_info();
while ( 1 )
{
read_dht11_dat();
delay(1000);//wait ls to refresh
}
return(0);
}
The while ( digitalRead( DHTPIN ) == laststate ) checks for a digital state of the pin for up to 255us, then breaks out of the outer for loop if it didn't find a change. I don't think the number 255 is significant, it's just some upper timeout limit. It's a crude hack used instead of properly using on-chip hardware timers with input capture.
Apparently the counter is meaningful for the algorithm too, so it seems to be measuring duty cycle of a PWM pulse or such. Again, in a very crude way.
I suppose hardware timers might not be easily accessible on a Rasp PI "PC in disguise" - this whole thing would be much easier and prettier with a bare metal microcontroller.
The line //ignore first 3 transitions if ( (i >= 4) && (i % 2 == 0) ) is code smell. Was this commented out on purpose or is it just some remains of someone's debugging attempts?
The lines
dht11_dat[j / 8] <<= 1;
if ( counter > 16 )dht11_dat[j / 8] |= 1;
just fills up a bitfield/byte array with ones or zeroes depending on if the counter was larger than 16us or not. The shift moves the previous data up, then the LSB is either set to 1 or remain 0.
The program sets a pin high for while to signal the device to transmit. The device transmits 40 bits of data, with a '1' and a '0' being signalled by the length of time the pin is held high. The program just samples the pin state until it's detected 85 edge transitions (which is just a few more that there should actually be), or until 255 usec elapses without an edge. The number of loop cycles between edges is used to determine whether to shift a '1' or a '0' in the data array.
The data is divided into five bytes, with the last byte being a checksum from the previous four.
The speed of communication is perhaps too fast for loop-sampling like this, and I get the impression that some of the parameters in the program might have been arrived at by trial-and-error. That's a reasonably safe thing to do on stock Pi, at least of a particular model, since there's so little variation between them.
Nevertheless, I can't help thinking that a better approach would be to trap the rising-edge interrupt provided in the GPIO firmware, followed by a single sample after a fixed delay. Just do this 40 times until all 40 bits have been read. I guess you'd need some back-out in case communication were lost.
I have written a C program which sorts an array of 50 of random numbers from 0 - 255. The highest number once sorted is displayed on 8 LEDs as binary digits. The same for the lowest sorted number. I fully understand the program however I need to write up a brief description of it and am struggling with these two functions:
void binaryLowesttNumber()
{
int remainder = lowArray; /* remainder is what I am going to be left with after taking away the value of the pins,
sets remainder as the lowest sorted number */
int j = 128; // value of pins in binary
int i = 7; // index of current pin
while (i >= 0)
{
if (remainder >= j) //if remainder is larger or equal to the value of the current pin
{
digitalWrite(pinArray[i], HIGH);
remainder = remainder - j; // takes value of pin away from remainder
j = j >> 1; // halves the value of j
i--; // moves to next pin
}
else
{
j = j >> 1; // halves the value of j
i--; // moves to next pin
}
}
}
void binaryHighestNumber()
{
int remainder = highArray; // same as binaryLowestNumber function except the remainder will be the highest sorted number
int i = 128;
int thisPin = 7;
while (remainder > 0)
{
while (remainder >= i)
{
double j = i / 2;
digitalWrite(pinArray[thisPin], HIGH);
remainder = remainder - i;
i = i - j;
thisPin--;
}
while (remainder < i)
{
int j = i / 2;
if (j >= 1)
{
i = i - j;
thisPin--;
}
else
{
i = 0;
}
}
}
}
Concentrate on what the function does (not on how it does that, your code explains that). What does function binaryHighestNumber() do? As I understood you correctly, your function sorts an array of 50 of random numbers from 0 - 255 and displays the highest number on 8 LEDs as binary digit. So a perfectly good and informative comment would be:
/**
* Sort an array of 50 random numbers from 0 - 255 and
* display the highest number on 8 LEDs as binary digit using 'digitalWrite()' function.
*/
void binaryHighestNumber()
...
Try to use doxygen format to document your code, that way it will be easy understandable by others who had worked with doxygen. And document what the function does, not how it does that. See Linux kernel coding commenting or GNU coding standard.
EDIT:
I don't see any sorting done in binaryHighestNumber() function. Are you sure this function sorts the array? As I inspect the function definition, all it does is to display a value stored in variable highArray on LEDs. Maybe a better comment would be this:
/**
* Display the highest number obtained from sorting array of 50 elements
* stored in a global variable 'highArray'
* on 8 LEDs as binary digit using 'digitalWrite()' function.
*/
void binaryHighestNumber()
...
EDIT2:
The intent was, that the question is how the code works and now how to comment it, so here we go. Let's concentrate on binaryHighestNumber().
Basically what the function does, is that it sets gpios high which number corresponds to the bit number in highArray. So for a highArray = 0b10101010 we want to light up gpios numbers 7, 5, 3 and 1 (numbering from 0). For highArray = 0b10100101 we want to light up gpios numbers 7, 5, 2 and 0.
The code binaryHighestNumber() keeps track of a remainder - the number substracted from the number of gpios already examined. The other is i - a value that is equal to 2 to the power of currently checked gpio number. thisPin is used to track the gpio number we currently check and it is equal to log2(i).
At first remainder = highArray and i = 128 and we want to check, if we should set gpio number 7 to high. We need to check if bit number 7 in the remainder is set or not. If the remainder is greater then 128, that means that the bit number 7 is set, that means that gpio number 7 needs to be set to high. If bit number 7 is not set, that means that remainder is lower then 128, we don't light the gpio. If the bit number 7 was set, we remove bit 7 from remainder (ie. substract i, which is eqaul to 128, from the remainder) and then bitshift i to the right by dividing it by 2. If bit number 7 was not set, we only bitshift i to the right.
Now remainder = highArray&0b01111111 and i = 64. We continue the process. If the remainder is greater than 64, that means that bit number 6 is set and we need to set gpio number 6 high, remove bit 6 from the remainder (by substracting i from it) and bitshift i to the left (by diving it by 2). If the number is lower then 64, we only bitshift i and continue.
Then remainder = highArray&0b00111111 and i = 32 and we continue until the remainder is equal to zero. (ie. remainder = highArray&0b00000000.
You can simplify the code, to somewhat easier form, like this:
void binaryHighestNumber()
{
int remainder = highArray; // same as binaryLowestNumber function except the remainder will be the highest sorted number
int i = 128;
int thisPin = 7;
while (remainder > 0) {
if (remainder >= i) {
digitalWrite(pinArray[thisPin--], HIGH);
remainder -= i;
i -= i/2;
}
if (remainder < i) {
if (i != 1) {
i -= i/2;
thisPin--;
} else {
i = 0;
}
}
}
}
or maybe like this:
void binaryHighestNumber()
{
int remainder = highArray; // same as binaryLowestNumber function except the remainder will be the highest sorted number
int i = 128;
int thisPin = 7;
while (remainder > 0) {
if (i != 0 && remainder >= i) {
digitalWrite(pinArray[thisPin--], HIGH);
remainder -= i;
i /= 2;
}
if (remainder < i) {
i /= 2;
thisPin--;
}
}
}
Pay attention to that i -= i/2; is not equal to i /= 2;, when i = 1. Also i have removed while loops, they don't change anything. I have removed j variables, they are not needed and don't change anything.
There is a much simpler way to check each bit in a byte and light up these gpios, but I think i will leave that to you to find out.
I need generate random 64-bit unsigned integers using C. I mean, the range should be 0 to 18446744073709551615. RAND_MAX is 1073741823.
I found some solutions in the links which might be possible duplicates but the answers mostly concatenates some rand() results or making some incremental arithmetic operations. So results are always 18 digits or 20 digits. I also want outcomes like 5, 11, 33387, not just 3771778641802345472.
By the way, I really don't have so much experience with the C but any approach, code samples and idea could be beneficial.
Concerning "So results are always 18 digits or 20 digits."
See #Thomas comment. If you generate random numbers long enough, code will create ones like 5, 11 and 33387. If code generates 1,000,000,000 numbers/second, it may take a year as very small numbers < 100,000 are so rare amongst all 64-bit numbers.
rand() simple returns random bits. A simplistic method pulls 1 bit at a time
uint64_t rand_uint64_slow(void) {
uint64_t r = 0;
for (int i=0; i<64; i++) {
r = r*2 + rand()%2;
}
return r;
}
Assuming RAND_MAX is some power of 2 - 1 as in OP's case 1073741823 == 0x3FFFFFFF, take advantage that 30 at least 15 bits are generated each time. The following code will call rand() 5 3 times - a tad wasteful. Instead bits shifted out could be saved for the next random number, but that brings in other issues. Leave that for another day.
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=0; i<64; i += 15 /*30*/) {
r = r*((uint64_t)RAND_MAX + 1) + rand();
}
return r;
}
A portable loop count method avoids the 15 /*30*/ - But see 2020 edit below.
#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF
#define LOOP_COUNT 1
#elif RAND_MAX/256 >= 0xFFFFFF
#define LOOP_COUNT 2
#elif RAND_MAX/256 >= 0x3FFFF
#define LOOP_COUNT 3
#elif RAND_MAX/256 >= 0x1FF
#define LOOP_COUNT 4
#else
#define LOOP_COUNT 5
#endif
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=LOOP_COUNT; i > 0; i--) {
r = r*(RAND_MAX + (uint64_t)1) + rand();
}
return r;
}
The autocorrelation effects commented here are caused by a weak rand(). C does not specify a particular method of random number generation. The above relies on rand() - or whatever base random function employed - being good.
If rand() is sub-par, then code should use other generators. Yet one can still use this approach to build up larger random numbers.
[Edit 2020]
Hallvard B. Furuseth provides as nice way to determine the number of bits in RAND_MAX when it is a Mersenne Number - a power of 2 minus 1.
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
_Static_assert((RAND_MAX & (RAND_MAX + 1u)) == 0, "RAND_MAX not a Mersenne number");
uint64_t rand64(void) {
uint64_t r = 0;
for (int i = 0; i < 64; i += RAND_MAX_WIDTH) {
r <<= RAND_MAX_WIDTH;
r ^= (unsigned) rand();
}
return r;
}
If you don't need cryptographically secure pseudo random numbers, I would suggest using MT19937-64. It is a 64 bit version of Mersenne Twister PRNG.
Please, do not combine rand() outputs and do not build upon other tricks. Use existing implementation:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
Iff you have a sufficiently good source of random bytes (like, say, /dev/random or /dev/urandom on a linux machine), you can simply consume 8 bytes from that source and concatenate them. If they are independent and have a linear distribution, you're set.
If you don't, you MAY get away by doing the same, but there is likely to be some artefacts in your pseudo-random generator that gives a toe-hold for all sorts of hi-jinx.
Example code assuming we have an open binary FILE *source:
/* Implementation #1, slightly more elegant than looping yourself */
uint64_t 64bitrandom()
{
uint64_t rv;
size_t count;
do {
count = fread(&rv, sizeof(rv), 1, source);
} while (count != 1);
return rv;
}
/* Implementation #2 */
uint64_t 64bitrandom()
{
uint64_t rv = 0;
int c;
for (i=0; i < sizeof(rv); i++) {
do {
c = fgetc(source)
} while (c < 0);
rv = (rv << 8) | (c & 0xff);
}
return rv;
}
If you replace "read random bytes from a randomness device" with "get bytes from a function call", all you have to do is to adjust the shifts in method #2.
You're vastly more likely to get a "number with many digits" than one with "small number of digits" (of all the numbers between 0 and 2 ** 64, roughly 95% have 19 or more decimal digits, so really that is what you will mostly get.
If you are willing to use a repetitive pseudo random sequence and you can deal with a bunch of values that will never happen (like even numbers? ... don't use just the low bits), an LCG or MCG are simple solutions. Wikipedia: Linear congruential generator can get you started (there are several more types including the commonly used Wikipedia: Mersenne Twister). And this site can generate a couple prime numbers for the modulus and the multiplier below. (caveat: this sequence will be guessable and thus it is NOT secure)
#include <stdio.h>
#include <stdint.h>
uint64_t
mcg64(void)
{
static uint64_t i = 1;
return (i = (164603309694725029ull * i) % 14738995463583502973ull);
}
int
main(int ac, char * av[])
{
for (int i = 0; i < 10; i++)
printf("%016p\n", mcg64());
}
I have tried this code here and it seems to work fine there.
#include <time.h>
#include <stdlib.h>
#include <math.h>
int main(){
srand(time(NULL));
int a = rand();
int b = rand();
int c = rand();
int d = rand();
long e = (long)a*b;
e = abs(e);
long f = (long)c*d;
f = abs(f);
long long answer = (long long)e*f;
printf("value %lld",answer);
return 0;
}
I ran a few iterations and i get the following outputs :
value 1869044101095834648
value 2104046041914393000
value 1587782446298476296
value 604955295827516250
value 41152208336759610
value 57792837533816000
If you have 32 or 16-bit random value - generate 2 or 4 randoms and combine them to one 64-bit with << and |.
uint64_t rand_uint64(void) {
// Assuming RAND_MAX is 2^31.
uint64_t r = rand();
r = r<<30 | rand();
r = r<<30 | rand();
return r;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
unsigned long long int randomize(unsigned long long int uint_64);
int main(void)
{
srand(time(0));
unsigned long long int random_number = randomize(18446744073709551615);
printf("%llu\n",random_number);
random_number = randomize(123);
printf("%llu\n",random_number);
return 0;
}
unsigned long long int randomize(unsigned long long int uint_64)
{
char buffer[100] , data[100] , tmp[2];
//convert llu to string,store in buffer
sprintf(buffer, "%llu", uint_64);
//store buffer length
size_t len = strlen(buffer);
//x : store converted char to int, rand_num : random number , index of data array
int x , rand_num , index = 0;
//condition that prevents the program from generating number that is bigger input value
bool Condition = 0;
//iterate over buffer array
for( int n = 0 ; n < len ; n++ )
{
//store the first character of buffer
tmp[0] = buffer[n];
tmp[1] = '\0';
//convert it to integer,store in x
x = atoi(tmp);
if( n == 0 )
{
//if first iteration,rand_num must be less than or equal to x
rand_num = rand() % ( x + 1 );
//if generated random number does not equal to x,condition is true
if( rand_num != x )
Condition = 1;
//convert character that corrosponds to integer to integer and store it in data array;increment index
data[index] = rand_num + '0';
index++;
}
//if not first iteration,do the following
else
{
if( Condition )
{
rand_num = rand() % ( 10 );
data[index] = rand_num + '0';
index++;
}
else
{
rand_num = rand() % ( x + 1 );
if( rand_num != x )
Condition = 1;
data[index] = rand_num + '0';
index++;
}
}
}
data[index] = '\0';
char *ptr ;
//convert the data array to unsigned long long int
unsigned long long int ret = _strtoui64(data,&ptr,10);
return ret;
}
So, I made this code.
Basically, takes in the number, then if negative, converts it to positive, calculates its binary and then its one complement and then adds 1.
#include <stdio.h>
int main (void)
{
int bin[8]={0};
int sum[8];
int orig,num,i=0,j;
int addn[8] = {0,0,0,0,0,0,0,1};
int carry = 0;
printf("Please enter the number\n");
scanf("%d",&num);
if ( num < 0 )
{
orig = num;
num = -num;
}
while (num!= 0)
{
bin[8-i-1] = num%2;
num = num/2;
i++;
}
for ( j = 0; j < 8; j++ )
{
printf("%d",bin[j]);
}
printf("\n");
if ( orig < 0 )
{
for ( i = 0; i < 8; i++ )
{
if (bin[i] == 0)
bin[i] = 1;
else
bin[i] = 0;
}
for ( i = 0; i < 8; i++ )
{
sum[i] = ((bin[i]^addn[i])^carry);
carry = ((bin[i] & addn[i])| (bin[i] & carry) | (addn[i] & carry) );
}
printf("The 2's complement of the number is \n");
printf("%d",carry);
for ( i = 0; i < 8; i++ )
{
printf("%d",sum[i]);
}
printf("\n");
}
return 0;
}
When I enter the value as 4, it correctly displays its binary value. However, it shows the its 2 compliment as 111111010 ( This is with carry ). Why is this happening? The 2's compliment form of -4 should be different.
Also, is there any other method of converting a negative number to its 2's compliment form?
If you check the 1's complement you'll find that's correct.
The slip is, you're storing the MSB in num[0] and the LSB in num[7], so when you're adding, you need to begin at the 7 end, not the 0 end. Putting (8-i-1) in all the addition part, produces something more like :
./a.out
Please enter the number
-4
00000100
The 1's complement of the number is
11111011
The 2's complement of the number is
011111001
That looks almost right at the low end, but the sign bit looks wrong, because you suddenly are outputting 9 bits, may be you intend to show the overflowing carry? I'm a bit confused about your output intentions and I haven't even examined that part of the source carefully.
I won't post the fixed source yet, you should try to learn to debug it yourself by putting in the extra printf's and reasoning about how you input the number initially.
Thanks for the nifty example program, though it could do with some serious refactoring for clarity. Is it a study exercise? If so you really SHOULD learn to find errors yourself.
Here goes with the corrections I intended but didn't quite input correctly first time :)
So to check the 1's complement was correct :
printf("The 1's complement of the number is \n");
for ( j = 0; j < 8; j++ )
{
printf("%d",bin[j]);
}
printf("\n");
Before starting the add. Then to fix :
for ( i = 0; i < 8; i++ )
{
sum[8-i-1] = ((bin[8-i-1]^addn[8-i-1])^carry);
carry = ((bin[8-i-1] & addn[8-i-1])| (bin[8-i-1] & carry) | (addn[8-i-1] & carry) );
}
Originally I had typo ((bin[i-i-1]^addn but I didn't really care about exact results as I knew I had found what was wrong and could explain where the fault lay.