PDA

View Full Version : BCD question



keymuu
- 31st January 2009, 14:34
Hi!

Consider this code:



Divisor VAR byte[5]
H VAR WORD
b VAR BYTE
w VAR WORD

powerTen: ' for BCD conversion
select case b
case 0: w = 1
case 1: w = 10
case 2: w = 100
case 3: w = 1000
case 4: w = 10000
end select
return

H=37234

'convert to BCD and fill divisor
FOR b = 0 to 4
gosub powerTen
divisor [b] = (H/w) & $0f
next b
ENDIF



Suspecting that "(H/w) & $0f" does not work as one would think, that is
w=1 -> 37234/1 = 37234 & $F -> 4
w=2 -> 37234/10= 3723.4 & $F = 3723 -> 3
w=3 -> 37234/100=372.34 & $F= 372 -> 2
w=4 -> 37234/1000=37,234 & $F=37 -> 7
w=5 -> 37234/10000=3.7234 & $F=3 -> 3

The array is filled with 3, that is 33333 !:mad:

The goal is to find in that array 37234...

So I fail to understand what is wrong and how to amend? :o

Can anybody explain why that code doesn't work

Thanks :)

Bruce
- 31st January 2009, 16:48
I'm not sure how you're testing your Divisor array, but it should not be filled with 3's.

What you should actually be seeing is something like this;


b = 0 : Divisor 0 = 2
b = 1 : Divisor 1 = 11
b = 2 : Divisor 2 = 4
b = 3 : Divisor 3 = 5
b = 4 : Divisor 4 = 3
Divisor[b] should always contain the low byte of the result H/w anded with $0F.

If you just want to extract individual digits from H, then let PBP do it for you with the DIG
operator.


FOR b = 0 to 4
divisor [b] = H DIG b
NEXT b
This divides by 10 returning the remainder.

Example: If H = 37234 then

b = H DIG 0 = 37234/10 = 3723.4 <-- Now b = 4

b = H DIG 1 = 37234/10 = 3723.4. 3723/10 = 372.3 <-- Now b = 3

b = H DIG 2 = 37234/10 = 3723.4. 3723/10 = 372.3. 372/10 = 37.2 <-- Now b = 2

Etc,,

Your entire program gets reduced to this;


Divisor VAR byte[5]
H VAR WORD
b VAR BYTE

Main:
H=37234

'fill divisor with digits 0 to 4 from H
FOR b = 0 to 4
divisor [b] = H DIG b
NEXT b
GOTO Main

END

keymuu
- 31st January 2009, 19:53
I'm not sure how you're testing your Divisor array, but it should not be filled with 3's.

What you should actually be seeing is something like this;


b = 0 : Divisor 0 = 2
b = 1 : Divisor 1 = 11
b = 2 : Divisor 2 = 4
b = 3 : Divisor 3 = 5
b = 4 : Divisor 4 = 3
Divisor[b] should always contain the low byte of the result H/w anded with $0F.

If you just want to extract individual digits from H, then let PBP do it for you with the DIG
operator.


FOR b = 0 to 4
divisor [b] = H DIG b
NEXT b
This divides by 10 returning the remainder.

Example: If H = 37234 then

b = H DIG 0 = 37234/10 = 3723.4 <-- Now b = 4

b = H DIG 1 = 37234/10 = 3723.4. 3723/10 = 372.3 <-- Now b = 3

b = H DIG 2 = 37234/10 = 3723.4. 3723/10 = 372.3. 372/10 = 37.2 <-- Now b = 2

Etc,,

Your entire program gets reduced to this;


Divisor VAR byte[5]
H VAR WORD
b VAR BYTE

Main:
H=37234

'fill divisor with digits 0 to 4 from H
FOR b = 0 to 4
divisor [b] = H DIG b
NEXT b
GOTO Main

END

Thank you Bruce :)

Of course, I forgot the DIG and tried to do the same thing the "basic way", as a algorithm would tell you, so still wondering way it did not work?
Consider that there would not be a DIG statement then the answer wouldn't be as easy as with DIG :rolleyes: And then the original idea modified should work, shouldn't it?

Nevertheless, thank you again Bruce for being alert, you have a open mind...:cool:

I already tested it with DIG and, of course, it works like ... well... a great thing...

Bruce
- 31st January 2009, 22:26
You can do the same thing without DIG.


Main:
H=37234

'fill divisor with digits 0 to 4 from H
FOR b = 0 to 4
divisor[b] = H//10
H=H/10
NEXT b
GOTO Main
As a learning exercise, see if you can figure out why this works the same as DIG - or come
up with another method...;o}

keymuu
- 1st February 2009, 13:13
You can do the same thing without DIG.


Main:
H=37234

'fill divisor with digits 0 to 4 from H
FOR b = 0 to 4
divisor[b] = H//10
H=H/10
NEXT b
GOTO Main
As a learning exercise, see if you can figure out why this works the same as DIG - or come
up with another method...;o}

Ok, Bruce you are also a teacher :)

As earlier said, I did not remember the DIG statement and obviously not modulus divider "//" neither.

That piece of code is clear and surely should work, however, if wouldn't work as expected then again there would be something to marvel over ;) But fortunately that is not the case....

So if we compare the "original" and your excellent DIG interpreter:


a)
FOR b = 0 to 4
gosub powerTen
divisor [b] = (H/w) & $0f
next b
b)
FOR b = 0 to 4
divisor[b] = H//10
H=H/10
NEXT b


Still wondering what is wrong in a?
If we convert those code fragments to algorithms then them would be something like this:
a) divide H with power of ten (10^n, when goes n=0..4) to get rid of the decimals, isolate the lsd and store it. Do it five times.
b) isolate the lsd with H mod 10, store it and truncate H with one digit. Do it five times. Simple and clear algorithm....

I just don't grasp what is wrong with a, I do not need it anymore, just wondering :confused:

Bruce
- 1st February 2009, 18:12
Still wondering what is wrong in a?

OK let's work through this a bit to see what's wrong with a.

On the 1st pass;

H = 37234
w = 1

37234/1 = 37234. Not much help so far. This is $9172 in HEX.

$9172 has a high byte of %10010001 & a low byte of %01110010.

Since Divisor is a byte array, Divisor[b] will always be loaded with
the low byte of the result (H/w) & $0F.

Now take your low byte %01110010 & AND it with %00001111. The result is
%00000010 or 2d, which, of course, isn't what you're expecting.

Do you see how this is working?

Not yet! OK we'll do one more;

on the 2nd pass;

H = 37234
w = 10

37234/10 = 3723.4. The .4 is lost so you have 3723, which = $E8B.

$E8B has a high byte of %00001110 & a low byte of %10001011.

Now take your low byte %10001011 & AND it with %00001111. The result is
%00001011 or 11d, which again is not what you're expecting.

OK - one more pass;

On the 3rd pass H still = 37234 and w = 100.

37234/100 = 372.34. Toss the .34 and you're left with 372, which = $174.
The high byte is %00000001 the low byte is %01110100.

The low byte %01110100 & %00001111 = %00000100 or 4d. You expected a
2d, but it returned 4d. Now you know why...;o}

That's how a is working. Just follow it along. It's really simple if you just take it
apart step-by-step.