Hi ladies and gents,

Next exercise is the following:

Write the function which we can declare as follows:
unsigned char bcd (int n);

The idea of this function is to store the last two decimal numbers of n into a 'binary coded decimal' byte and to return this value. So, when n would be equal to 12345, then the 4 and the 5 from this number would be encoded into the 8 bits as:

0100 0101

Now, I tried to use the code Narue gave me, to cut the decimal number into pieces like this:

int main()
{
	int a = 12345;
	int x;

	x = bcd(a);
	cout << x <<endl;

	return 0;
}

unsigned char bcd (int n)
{
	int i;
	char totvalue;
	ostringstream out;

	out<< n;
	string s = out.str();

	for (i = 1; i >= 1; --i)
	{			
		totvalue = s[i] - '0';
                          start changing decimal number into binary code...
	}
	return totvalue;
}

THis way, I can get the separate values of that decimal number and then try to change them into a binary code?
Thing is, I'm not sure this is actually the correct/best way of dealing with this?

Questions are,
1) could someone show me wich is the best way to deal with this and keeping in mind that I have to use:

unsigned char bcd (int n);

2) Problem occurs is, that how can I return two separate pieces of binary code: first 0101 and then 0100 or is it 0100 and then 0101. Quiete frankly, I don't understand how this is accomplished. Or do you have to send it in one time 0100 0101?

3) Also, how can an unsigned char return a binary code 0100 0101?

Thanks for the help guys, maybe the solution is made out of the several exercises I allready made in wich you helped me aswell, but I just don't see how I can solve it :-|

>out<< n;
>string s = out.str();
In this case (since you're taking the rightmost digits) arithmetic operations may be easier:

if ( n >= 10 ) { // Make sure there are two digits
  int a = n % 10;
  int b = ( n / 10 ) % 10;
}

>how can I return two separate pieces of binary code
It's an exercise in bit packing. The two 4 bit chunks are packed together in an unsigned char:

( b << 4 ) | a

>3) Also, how can an unsigned char return a binary code 0100 0101?
The char type has to be at least 8 bits by definition, so you can easily fit two 4 bit pieces there.

Well, thanks for the help Narue,

With the code you showed, I managed to make this:

unsigned char bcd (int n);

int main()
{
	int value = 12345;
	int x;

	x = bcd(value);
	cout << x <<endl;

	return 0;
}

unsigned char bcd (int n)
{
	char binary[80], temp[80], code;
	int remain = 0, decimal = 0;
	int a, b, i, k = 0;

	if (n >= 10)
	{
		a = n % 10;
		b = (n / 10) % 10;
	}

	for (i = 0; i < 2; ++i)
	{
		if (i == 0)
			decimal = a;
			else
			decimal = b;

			do
			{
				remain = decimal % 2;
				decimal = decimal / 2;
				temp[k++] = remain + 0x30;
			}
			while (decimal > 0);

				while (k >= 0)
				{
					binary[n++] = temp[--k];
				}
				binary[n-1] = 0;             

				code = ( binary[n] << 4 ) | binary[n];
	}

	return code;
}

Problem is that alltough I'm not getting any error messages, when I debug the program and get towards this part of the program:

binary[n++] = temp[--k];

I get a message: Unhandled exception in LAOef4_6.exe: 0xC0000005: Access Violation :o

I'm assuming I did something seriously wrong here, tough it doesn't crash the program :?:

>0xC0000005: Access Violation
An access violation means you tried to access memory outside of your address space. After debugging lots of these problems, you begin to get a sense for what memory addresses look "wrong" for what you're trying to do. 0xC0000005 looks wrong, and most likely one of your indices is accessing an array out of bounds.

Of course, your solution is way too long. You could practically paste the code I gave you into your function body and be set:

unsigned char bcd ( int n )
{
  if ( n >= 10 ) { // Make sure there are two digits
    int a = n % 10;
    int b = ( n / 10 ) % 10;

    return ( b << 4 ) | a;
  }

  return n;
}

>Of course, your solution is way too long. You could practically paste the code I gave you into your function body and be set:

Well, I did use your code, but using it solely doesn't make the decimal number into a binary code, that's why I used the remaining code?

>but using it solely doesn't make the decimal number into a binary code
The binary code is packed inside an unsigned char. The only way to get it out is to access the value bit by bit:

while ( value != 0 ) {
  cout<< !!( value & 1 );
  value >>= 1;
}

You're confusing a binary code with the string representation of a binary code.

I was under the impression that the return value might be expected to be an unsigned int, and that the expected input/output might be as follows.

#include <stdio.h>

unsigned int dec2bcd(unsigned int dec)
{
   unsigned int bits, bcd = 0;
   for ( bits = 0; dec; bits += 4, dec /= 10 )
   {
      bcd |= dec % 10 << bits;
   }
   return bcd;
}

int main()
{
   unsigned int value = 12345, result = dec2bcd(value);
   printf("bcd(%u) = 0x%X [%u]\n", value, result, result);
   return 0;
}

/* my output
bcd(12345) = 0x12345 [74565]
*/

Or am I just off today?

Dave and especially Narue,

Thanks for the help, but I'm giving up on this, I simply am not getting what is asked in this exercise and the pieces of code you are giving me Narue are just confusing me more and more and instead of leading me to the solution is getting me further and further away :!:

To say it as it is, I'm just not cut out for this, I hoped to learn this as a fun hobby, but actually is getting me frustrated as it's not working out as it should.

STill, you guys are top notch and I enjoyed learning from you tough I didn't remember all of it and certainly so it seems didn't understand all of it

>but I'm giving up on this
Not totally I hope. You've shown a lot of promise. Programming is hard. There's no getting around it, so you just have to keep going until you finally have a flash of insight and understand what was confusing you. Then you can move on to a new thing that confuses you. This process is repeated until you die.

>Not totally I hope.
That was my intention yes, but then again, I do like to try and learn this, it's just so frustrating that even when getting help from you and Dave, I STILL can't figure it out :!:

>

while ( value != 0 )
{
  cout<< !!( value & 1 );
  value >>= 1;
}

When I try this with the value 12345, I get this as a binary code: 10011100000011
Tough, the code should be 0001 0010 0011 0100 0101 :?:

>12345 -> 0001 0010 0011 0100 0101
I understand that the decimal value equals this binary code, the problem is, how in the h*ll do I get (0100 0101) into a return value (unsigned char) :mad:

>12345 -> 0001 0010 0011 0100 0101
I understand that the decimal value equals this binary code

The left is not the same value as the right. :?:

Perhaps some debugging printfs can help.

#include <stdio.h>

unsigned int dec2bcd(unsigned int dec)
{
   unsigned int bits, bcd = 0;
   for ( bits = 0; dec; bits += 4, dec /= 10 )
   {
      printf("dec = %5u, bits = %2u, bcd = %6u (0x%04x)\n", dec, bits, bcd, bcd);
      bcd |= dec % 10 << bits;
   }
   return bcd;
}

int main()
{
   unsigned int value = 12345, result = dec2bcd(value);
   printf("bcd(%u) = 0x%X [%u]\n", value, result, result);
   return 0;
}

/* my output
dec = 12345, bits =  0, bcd =      0 (0x0000)
dec =  1234, bits =  4, bcd =      5 (0x0005)
dec =   123, bits =  8, bcd =     69 (0x0045)
dec =    12, bits = 12, bcd =    837 (0x0345)
dec =     1, bits = 16, bcd =   9029 (0x2345)
bcd(12345) = 0x12345 [74565]
*/

>I STILL can't figure it out
Binary is a bitch to understand at first. This has nothing to do with your ability, it's a difficult subject for anyone to wrap their mind around when they first start working with.

>When I try this with the value 12345, I get this as a binary code: 10011100000011
That loop only prints the bits of a value. Unless 12345 has already been binary coded, you should expect 11000000111001, which because the loop prints the bits in reverse order, gives you 10011100000011. You're still confusing things:

12 = 1100

This is a binary value that is directly equivalent to the integral value 12. Notice how the value 12 fits in 4 bits. My loop prints this.

12 = 00010010

This is a binary encoding of the two integral digits 1 and 2. Notice how there's no way to fit this encoding in 4 bits, so 8 bits are used. Your bcd function returns this.

>how in the h*ll do I get (0100 0101) into a return value (unsigned char)
Return the integral value 69. 69 has the bit pattern 01000101, which is what you want and why I said this is a bit packing exercise.

Well, after the additional tips you gave, I got to the point that I'm getting an output of 1010001, apparantly, I'm still missing one 0 at the back :-|

THe code I used was this:

int main()
{
	int value = 12345;
	char x;

	x = bcd(value);

	while ( x != 0 )
	{
		cout<< !!( x & 1 );
		x >>= 1;
	}

	return 0;
}

unsigned char bcd (int n)
{

	if ( n >= 10 )
	{
		int a = n % 10;
		int b = ( n / 10 ) % 10;

		return ( b << 4 ) | a;
	}

	return n;
}

So, all I have to do know is reverse the value 1010001 into '0'100 0101, correct :?:

Also, could you explain how this piece of code works:

!!( x & 1 )

>12 = 1100
I understand this Narue, because four bits can have a maxim value of 15, wich also equals the amount in hex from 0 to 9 and A to F.

>12 = 00010010
This however I don't understand :?: I mean, I understand it to be eight bits

@ Dave,
Thanks for the additional info, however I didn't try out the code you wrote because I feared I would get even more confuzed then I allready am :!:

I did include the link you gave me into my favorites and will read the article later on, thanks for that :!:

>Also, could you explain how this piece of code works
x & 1 lets you access the low order bit of x. The double bang trick guarantees that the resulting value is normalized to 0 or 1. Figuring it out is a fun exercise, try taking away one !, then take away the other. Try using something other than 1 for the right hand side of the & and do the same thing.

>I mean, I understand it to be eight bits
Then you understand without understanding it seems. ;) Yes, it is eight bits, because you're taking each digit of the original number (12, or 1 and 2, or 0001 and 0010) setting aside four bits for each of them, and then pasting those four bit chunks together to get the binary code, 00010010.

Nope, not working :!:

When I use this code:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

unsigned char bcd (int n);

int main()
{
	int value = 12;
	char x;

	x = bcd(value);

	while ( x != 0 )
	{
		cout<< !!( x & 1 );
		x >>= 1;
	}

	return 0;
}

unsigned char bcd (int n)
{

	if ( n >= 10 )
	{
		int a = n % 10;
		int b = ( n / 10 ) % 10;
		return ( b << 4 ) | a;
	}

	return n;
}

My result is this binary code: 01001 :o When it should be 0001 0010 :rolleyes:

I tried out using

!( x & 1 );

I tried out using

( x & 1 );

I tried out using

!!( x & 2 );

I tried out ... several other changes in this piece of code, they all gave different outcomes, but to be honest, I don't know WHY it happend and I don't know why or when I would use these changes because I don't know what happens with the code:?:

I also changed this

return ( b << 4 ) | c;

into this

return ( a << 4 ) | b;

wich actually returned this: 100001
Why, I have no idea :?:

So, to make it short, after all tries and tribulations :D I still haven't found the solution to my exercise :!:

DARN

>Nope, not working
It's working fine, just not the way you want it to.

>My result is this binary code: 01001 When it should be 0001 0010
Okay, reverse what you got because the loop prints the low-order bits first:

10010

Now notice the condition for the printing loop, while x != 0. Because the loop only prints as long as there's a 1 bit somewhere in the value, leading 0's are ignored. So you're getting the correct output, it's just not formatted as you expected.

To be perfectly honest, that method of printing bits only has the advantage of being simple to write correctly the first time. Another easy (if incredibly obscure) way to print the bits properly is with bitset:

#include <bitset>
#include <iostream>

using namespace std;

unsigned char bcd (int n);

int main()
{
  int value = 12345;
  unsigned char x;

  x = bcd(value);
  cout<< bitset<8> ( x ).to_string<char, char_traits<char>, allocator<char> >() <<endl;

  return 0;
}

unsigned char bcd (int n)
{

  if ( n >= 10 )
  {
    int a = n % 10;
    int b = ( n / 10 ) % 10;

    return ( b << 4 ) | a;
  }

  return n;
}

You can do it manually without the aid of the standard library like so:

#include <bitset>
#include <iostream>

using namespace std;

unsigned char bcd (int n);

int main()
{
  int value = 12345;
  unsigned char x;

  x = bcd(value);
  for ( int i = 7; i >= 0; i-- )
    cout<< !!( x & ( 1U << i ) );

  return 0;
}

unsigned char bcd (int n)
{

  if ( n >= 10 )
  {
    int a = n % 10;
    int b = ( n / 10 ) % 10;

    return ( b << 4 ) | a;
  }

  return n;
}

But for the usual reasons, that's not as good of a solution. :)

[HOMER] DOH :!: [/HOMER]

Oh Narue, why do you allways make it look so simple :mrgreen:

>

cout<< !!( x & ( 1U << i ) );

I understand '!!' being used to make sure that only 0 or 1 are shown.

Like in the previous thread, you said that x & 1 was used for accessing the lower bit, but why is there U mentioned behind it :?:

>But for the usual reasons, that's not as good of a solution.
Why is the other solution better then :?:

Anyway, thanks for the help ;)

>Oh Narue, why do you allways make it look so simple
As you gain experience, hard things become simple and impossible things become hard. :)

>why is there U mentioned behind it
Force of habit. It's always a good idea to force all parts of a bitwise expression to unsigned types because the bitwise operators are surprisingly tricky to use with signed types. 1U basically says that 1 is an unsigned int rather than a signed int.

>Why is the other solution better then
The usual suspects:

1) Portability (the same code will work the same everywhere)
2) Reuse (you don't have to solve the same problems over and over)
3) Performance (the standard library is written to be fast)

This article has been dead for over six months. Start a new discussion instead.