# HP Forums

You're currently viewing a stripped down version of our content. View the full version with proper formatting.

The software library here has an excellent program with two routines that switch from floating mode to integer mode or back. It says that if the floating value is non integer it will be truncated. Unfortunately there is a bug in it. Sometimes it will truncate, e.g. 1234.567 will convert to 1234 correctly. But 1.2 converts to 872415233 decimal, instead of 1. I can't get my mind around what is happening. Can you help? Or suggest coding to work around the problem?

The reason this is an issue is that if for example you are in float mode with 3 decimal places and the number is 1.0001, you see it as 1.000. But it will convert incorrectly.

Here is the code:

```# HP-16C Integer-to-Float/Float-to-Integer
#      -Jamie Cox
# Usage:
# Press GSB A to convert a float number to 32-bit HEX
# Press GSB 9 to convert an integer to float
# Mnemonic: A is a hex digit, 9 is a decimal digit.
#   A & 9 are at opposite ends of the keypad
#
#
001 43,22,A   g LBL A	        # Convert Float to Integer
002 23	      HEX	        # Leaves value in Y and shift count in X
003 42 F      RRn               # Apply shift
004 2	      2			# 20 Hex gives 32-bit wordsize
005 0	      0
006 42 44     f WSIZE
007 43,4,3    g SF 3		# display leading zeros
008 43 21     g RTN
009 43,22,9   g LBL 9		# Convert Integer to Float
010 0	      0
011 42, 45,3  f FLOAT 3		# Set # digits after decimal
012 43 21     g RTN		# That was easy
```

Edited: 5 July 2008, 6:30 p.m.

Starting with 1.2 could you document the values at each stage.

OK here we go.
(Window 1 gives us the high order part in each case)

```We are in float mode.
1.2
HEX
FFFFFFE1 .h  (checking window 1 shows FFFFFF)
You also need to know Y at this stage.
It shows:
9999999A  .h (checking window 1 shows 000000)
RRn
34000001  .h (checking window 1 shows 333333)
The rest just changes with word size from 56 to 32 and sets it to display leading zeroes
The result in decimal is 14411518821007361 which is nowhere near 1!
Here is the same but starting with 2
2
HEX
FFFFFFE2 (window 1 is FFFFFF)
Y is 80000000 (window 1 is 000000)
RRn
00000002  .h (window 1 is 000000)
Correct result.
```

Edited: 6 July 2008, 3:51 p.m.

I think that RRn (Rotate-right-N) isn't the way to do this, you need to shift-right-N but this requires some looping because there isn't a SRn function on the 16C. However there's a way to obtain the integer part of a number in floating point mode follow this link. Once you have the integer part in floating point mode you can use RRn when you're back in integer mode and you'll get the right answer.

The program described in this link works definitively on a 16c (just tested).

Thanks. That gives useful code that one can add to force it to an integer before converting.

It is very good to learn how to do an RND in 5 steps or an INT in 15 steps (for positive numbers); I did not know how to do that.

It would be still be good to try to make the conversion work as it should - perhaps using SR as you suggest. Also the conversion doesn't handle negative numbers at the moment - they come out positive. (The opposite conversion, to float, has no problems and does handle negative numbers.)

I have finally solved it. This proved to be quite difficult. By solved it I mean that it must work correctly in all conditions:

```- Both positive and negative numbers.
- Fractional numbers must convert correctly with the fractional part removed.
- It must work with negative numbers in both 1's complement and 2's complement.
- It must work if using 64 bit wordsize.
Possible methods:
- RRn is only suitable if the value is an integer already. Does not work with negatives.
- SR in a loop is better but does not work with negatives.
- Divide by 2 in a loop does not work with negatives.
- ASR works with positives and negatives,
but if in 2's complement mode a fractional negative number gives the wrong result,
e.g. -1.2 becomes -2.
Solution:
- Use ASR in a loop
- Capture the sign in a flag and restore at the end.
```
The solution takes about 19 steps.

I can see quite a neat way to split this into routines and package it with an INT and a RND function (and the simple int to float function) that will also work correctly in all conditions.
The whole lot should take about 50 steps.

Thanks for your help. I'll put the final versions in a message here and offer them to the library.

Edited: 7 July 2008, 10:13 a.m.

Here is the debugged code to switch between float and int. Any suggestions very welcome.

```Step	ListKey	Mnemo	Comments
001	43,22,a	g LBL A	Float to Int
002	43,5,2	g CF 2	Store sign
003	43 2	g x<0
004	43,4,2	g SF 2
005	43 8	g ABS
006	23	HEX	Convert
007	43 8	g ABS
008	44 32	STO I
009	34	x<>y
010	43,22,1	g LBL 1
011	43 b	g ASR
012	43 23	g DSZ
013	22 1	GTO 1
014	0	0	Set wordsize to 64
015	42 44	f WSIZE
016	43,6,2	g F? 2	Restore sign
017	49	CHS
018	43,4,3	g SF 3	Show leading zeroes
019	43 21	g RTN
020	43,22,9	g LBL 9	Int to Float
021	0	0
022	42,45,4	f FLOAT 4	Number of decimal places
023	43 21	g RTN
```

Here is the same debugged code to switch between Float and Int. This time it is integrated with routines for INT and RND.
All suggestions very welcome.

```Instructions:
GSB A Float to Int
GSB 9 Int to Float
GSB B INT
GSB D RND
Step	ListKey	Mnemo	Comments
001	43,22,2	g LBL 2	Subroutine to store sign
002	43,5,2	g CF 2
003	43 2	g x<0
004	43,4,2	g SF 2
005	43 8	g ABS
006	43 21	g RTN
007	43,22,3	g LBL 3	Subroutine to round
008	42 49	f EEX
009	9	9
010	40	+
011	43 36	g LSTx
012	30	-
013	43 21	g RTN
014	43,22,a	g LBL A	Float to Int
015	21 2	GSB 2
016	23	HEX	Convert
017	43 8	g ABS
018	44 32	STO I
019	34	x<>y
020	43,22,1	g LBL 1
021	43 b	g ASR
022	43 23	g DSZ
023	22 1	GTO 1
024	0	0	Set wordsize to 64
025	42 44	f WSIZE
026	43,4,3	g SF 3
027	43,22,4	g LBL 4
028	43,6,2	g F? 2	Restore sign
029	49	CHS
030	43,4,3	g SF 3	Show leading zeroes
031	43 21	g RTN
032	43,22,b	g LBL B	INT
033	21 2	GSB 2
034	21 3	GSB 3
035	43 3	g x>y	Adjust rounded result by 1
036	1	1
037	0	0
038	36	Enter
039	1	1
040	0	0
041	10	/
042	30	-
043	22 4	GTO 4
044	43,22,d	g LBL D	RND
045	21 2	GSB 2
046	21 3	GSB 3
047	22 4	GTO 4
048	43,22,9	g LBL 9	Int to Float
049	0	0
050	42,45,4	f FLOAT 4	Number of decimal places
051	43 21	g RTN
```