The Museum of HP Calculators

HP Forum Archive 21

[ Return to Index | Top of Index ]

Understanding HP-16C integer division
Message #1 Posted by Jimi on 16 Oct 2012, 3:16 a.m.

I was going through the user guide for the HP-16C. On page 41 is this example. I see that it gets the answer it does, but I don't understand how it gets that answer.

The left are the commands from the example, the right is the screen display.

[HEX] 5A0 [ENTER]      5A0 h
[OCT] 177764        177764 o
[/]                 177610 o
[HEX]                 FF88 h

So we are dividing 0x5A0 by 0177764. In my integer world, this should be zero. Can anyone give me the logic behind an answer of 0xFF88?

Edited: 16 Oct 2012, 3:17 a.m.

      
Re: Understanding HP-16C integer division
Message #2 Posted by Paul Dale on 16 Oct 2012, 3:58 a.m.,
in response to message #1 by Jimi

Expressing everything in decimal:

        1440 / -12 = -120

Look at the status at the top of the example. Two's complement, sixteen bit arithmetic.

- Pauli

            
Re: Understanding HP-16C integer division
Message #3 Posted by jimi on 16 Oct 2012, 5:24 p.m.,
in response to message #2 by Paul Dale

The example in the book is 16-bit, 2's complement.

I understand the decimal representation of the bits.

0x5A0   = 00000101 10100000 = 1440
0177764 = 11111111 11110100 = -12 
I can understand that the answer is -120 (0xff88), at least logically doing the math in my head. I guess what I don't understand is how you get:
00000101 10100000 /
11111111 11110100
=================
11111111 10001000
I guess I'm just trying to work in my head how it is done. I program in C a lot, so usually think in terms of that. Trying it, if I set each value to a short, then if I do the divide, I get -120. If I use a long, I don't, as 0177764 doesn't set the sign bit in a 32-bit number. You just get zero.

So why does the division work if the number is negative, or am I thinking about it wrong.

I'm guessing the HP-16C has it's division routine coded to handle these different cases. How could you code a division routine so that it always handled things correctly?

                  
Re: Understanding HP-16C integer division
Message #4 Posted by Paul Dale on 16 Oct 2012, 5:41 p.m.,
in response to message #3 by jimi

The WP 34S has such an integer divide coded. I suspect the 16c is quite different although the answers are the same. The 16c hardware lacks division as a cpu instruction.

My implementation gets rid of the signs, does the division using positive numbers and puts back the appropriate sign at the end.

- Pauli

      
Re: Understanding HP-16C integer division
Message #5 Posted by Luiz C. Vieira (Brazil) on 16 Oct 2012, 6:39 a.m.,
in response to message #1 by Jimi

HI.

Just to add one suggestion to Paul's clarifying follow-up, try this:

[f][DEC]    -120 d <shown briefly or as long as you keep [DEC] pressed>
Cheers.

Luiz (Brazil)

Edited: 16 Oct 2012, 6:39 a.m.

      
Re: Understanding HP-16C integer division
Message #6 Posted by Eddie W. Shore on 16 Oct 2012, 8:32 a.m.,
in response to message #1 by Jimi

Quote:
I was going through the user guide for the HP-16C. On page 41 is this example. I see that it gets the answer it does, but I don't understand how it gets that answer.

The left are the commands from the example, the right is the screen display.

[HEX] 5A0 [ENTER]      5A0 h
[OCT] 177764        177764 o
[/]                 177610 o
[HEX]                 FF88 h

So we are dividing 0x5A0 by 0177764. In my integer world, this should be zero. Can anyone give me the logic behind an answer of 0xFF88?


Jimi,

A wild educated guess: It might be the bit size you are working with. I am not an expert with the 16C, I don't own a physical one but an app, but I think you can change it. I don't know how though.

Converting 5A0 h to binary gives me 10100000 b (1440) While 17 7764 o gives me 11110100 b (-12)

I am thinking that the 16C is currently working with 8 bits.

-------------- For comparison purposes, I redid the calculation on the 32 SII and got 0.

5A0 h (0101 1010 0000 b, 1,440) ENTER 177764 o (1111 1111 1111 0100 b, 65,524) /

Result: 0 (everywhere. I think the 32 sII operates on 36 bits)

Eddie

            
Re: Understanding HP-16C integer division
Message #7 Posted by Luiz C. Vieira (Brazil) on 16 Oct 2012, 9:00 a.m.,
in response to message #6 by Eddie W. Shore

Hi, Eddie.

The HP16C allows unsigned, 1's and 2's complement mode representation. The HP32S only works with unsigned, so it cannot emulate the HP16C results, which are correct if 2's complement mode is set.

Cheers.

Luiz (Brazil)

                  
Re: Understanding HP-16C integer division
Message #8 Posted by Eddie W. Shore on 16 Oct 2012, 9:05 a.m.,
in response to message #7 by Luiz C. Vieira (Brazil)

Luiz,

Good to know. Question: what is the difference between 1's and 2's complement? I thought 2's complement was another way of negating numbers.

Thanks,

Eddie

Edited: 16 Oct 2012, 9:05 a.m.

                        
Re: Understanding HP-16C integer division
Message #9 Posted by Paul Berger (Canada) on 16 Oct 2012, 9:58 a.m.,
in response to message #8 by Eddie W. Shore

1s compliment is just flipping all of the bits 2s compliment flips all the bits and adds 1.

                        
Re: Understanding HP-16C integer division
Message #10 Posted by Walter B on 16 Oct 2012, 1:06 p.m.,
in response to message #8 by Eddie W. Shore

Get a 34S and you can experience it :-)

                        
Re: Understanding HP-16C integer division
Message #11 Posted by Neil Hamilton (Ottawa) on 16 Oct 2012, 1:39 p.m.,
in response to message #8 by Eddie W. Shore

One's compliment is an alternate way of specifying negative numbers. Both 2's and 1's comp have their advantages in certain areas. For example, the IPv4 checksum in an IPv4 datagram is in a 1's comp representation because this makes the calculation endian agnostic. This is not so using 2's comp.

It is interesting to note that because negatives are just the compliment of their positive representation, 1's comp has 2 different representations for zero: a 'negative' zero and a 'positive' zero (if there is such a thing for either :-). The negative zero is sometimes displayed as -0 (thinking back semi-fondly of my CDC 6400 days). You can see this on an HP-16C (or DM-16CC, etc.) by doing the following:

DEC
4
f WSIZE
f 1'S
0
BIN       <- shows "0 B"
CHS       <- shows "1111 B"
CHS       <- shows "0 B"
DEC       <- shows "0 D"
CHS       <- shows "-0 D"
CHS       <- shows "0 D"

Positive numbers are identical for both 1's and 2's comp. They only differ in their negative representation. Because there is this oddity of -0, the dynamic range of 1's comp negative numbers is 1 less than that of 2's comp.

For example, assuming a 4 bit number, here is what they look like:

Decimal   2's comp   1's comp
  7         0111      0111
  6         0110      0110
  5         0101      0101
  4         0100      0100
  3         0011      0011
  2         0010      0010
  1         0001      0001
  0         0000      0000  
 -0         N/A       1111 
 -1         1111      1110  
 -2         1110      1101
 -3         1101      1100
 -4         1100      1011
 -5         1011      1010
 -6         1010      1001
 -7         1001      1000
 -8         1000      N/A

I am sure someone more educated than I can tell why the 2's comp won out over 1's comp. Most of the machines I used in the early 70's were from Control Data Corporation and they used 1's comp (to the best of my recollection). It would be interesting to see a history of the various architectures and when things stabilized in the predominant 2's comp world we see now.

                              
Re: Understanding HP-16C integer division
Message #12 Posted by Marcus von Cube, Germany on 16 Oct 2012, 2:56 p.m.,
in response to message #11 by Neil Hamilton (Ottawa)

2's complement has the advantage that addition and subtraction work the same as in unsigned mode. In an 8 bit unsigned world, numbers range from 0 to 255. 2'complement numbers range from -128 to +127 where +127 + 1 wraps to -128. It's just a matter of interpreting the results with the left most bit set. In 1's complement, addition of negative numbers needs special treatment.

                                    
Re: Understanding HP-16C integer division
Message #13 Posted by Dale Reed on 16 Oct 2012, 10:50 p.m.,
in response to message #12 by Marcus von Cube, Germany

Marcus has hit the nail on the head. Neil, look at your own 1's complement and 2's complement bit patterns. In a "simple binary adder", the 1's complement case implies that -0 + 1 = 0 !!! (The bit pattern wraps from 1111 to 0000, kind of like 999 + 1 = (1)000, using a 3-digit decimal adder.) In 2's complement, the "simple binary adder" correctly says that -1 + 1 = 0 (same bit patterns). This behavior of 2's complement addition/subtraction close to zero is what's important, and keeps the hardware simple and fast.

Notice, however, with 2's complement, what happens at the 7 + 1 = -8 end, though. You simply MUST be aware of the word length and representation. I've seen any number of cases of code where the programmer was using an 8-bit signed (2's complement) integer and wrote an expression like:

IF (x = 200) THEN ..... END_IF;

There are two problems here. First, the Editor/Compiler in Question is not smart enough to even warn about this, even though it "knows" the Type of "x". Second, and more important, the Implementation in Question treats "200" as a 32-bit signed integer constant, and it promotes the x operand to a 32-bit signed integer before it performs the operation. x is always promoted by "sign extension" -- taking "bit 7" (the high-order bit of the 8-bit integer) and copying it out to the new bits of higher order, thus maintaining its arithmetic value. So the comparison is comparing x (which is always in the range -128 .. 127) to 200, which will never evaluate true.

The first edition of Kernighan and Ritchie "The C Programming Language" kind of "punted" (and told the truth about varied implementations at the time) and stated that the only thing you can infer about integer types from the language definition (not knowing the details of the language implementation) is that a "long int" is "at least as long" as an "int", and an "int" is "at least as long" as a "short int". Ever since, people have debated in standards committees (so, ANSI-C) and written (fairly confusing, in some implementations) header files and compiler options to determine the sizes of these integers.

When the industrial Programmable Controller language standard IEC-61131-3 was written, they cast it in stone: SINT (short signed integer) = 8 bits, INT = 16 bits, DINT (double integer) = 32 bits, and LINT (long integer) = 64 bits. These are all 2's complement signed, to get back on topic....

Dale

                        
Re: Understanding HP-16C integer division
Message #14 Posted by David Hayden on 16 Oct 2012, 1:47 p.m.,
in response to message #8 by Eddie W. Shore

One advantage of 2's complement over 1's complement is that it has only one representation of zero. 1's complement has negative and positive zero.

As I recall, another significant advantage of 2's complement is that the same hardware can add and subtract numbers regardless of whether they're positive or negative.

                              
Re: Understanding HP-16C integer division
Message #15 Posted by Neil Hamilton (Ottawa) on 16 Oct 2012, 2:12 p.m.,
in response to message #14 by David Hayden

I think this single H/W holds for 1's comp as well. It is just the interpretation of the result that is different. If you are consistently X's compliment, then it is self consistent.

Take the following examples (tried on my trusty 48):

Decimal:   -6 + 6 = 0
1's comp: #1001b + #0110b = #1111b (correct, -0)
2's comp: #1010b + #0110b = #0000b (correct)

Decimal: -6 + 5 = -1 1's comp: #1001b + #0101b = #1110b (correct, -1) 2's comp: #1010b + #0101b = #1111b (correct, -1)

A few years ago I was involved in building a complete TCP/IP stack in H/W and don't recall I had to do anything special with the IPv4 checksum. Mind you, since the rest of the design was is 2's comp, we did have to interpret the 2 forms of 0 when doing comparisons (there goes that self consistent thing... :-).

                                    
Re: Understanding HP-16C integer division
Message #16 Posted by Brian N on 16 Oct 2012, 3:21 p.m.,
in response to message #15 by Neil Hamilton (Ottawa)

Neil,

You forgot the third case:

Decimal: -6 + 7 = 1
1's comp: #1001b + #0111b = #0000b (incorrect!)

The same H/W adder can be used to add unsigned or signed integers with 2's comp. But, not with 1's comp -- you would need to increment the result by one if a carry resulted from the adder.

I'm pretty should this is why 2's comp won out and is used almost universally now in digital systems.

-Brian

                                          
Re: Understanding HP-16C integer division
Message #17 Posted by Neil Hamilton (Ottawa) on 16 Oct 2012, 3:37 p.m.,
in response to message #16 by Brian N

Argh! Looks like you are right! Looking back in my (really old) Verilog I see I folded the carry into the final summation.

That would definitely answer the question of why one overtook the other.

Thanks for picking that up.

                        
Re: Understanding HP-16C integer division
Message #18 Posted by Luiz C. Vieira (Brazil) on 16 Oct 2012, 2:03 p.m.,
in response to message #8 by Eddie W. Shore

Hi.

Now you have many references, but somehow I thought it would be easier to let HP explain it by itself, so I took these pages from the original HP16C manual, have them 'OCR'ed' and then I composed the PDF.

Cheers.

Luiz (Brazil)

                              
Re: Understanding HP-16C integer division
Message #19 Posted by Eddie W. Shore on 16 Oct 2012, 9:13 p.m.,
in response to message #18 by Luiz C. Vieira (Brazil)

Thanks Luiz! Thanks everyone!


[ Return to Index | Top of Index ]

Go back to the main exhibit hall