In this thread

http://www.hpmuseum.org/forum/thread-9156.html
Joe Horn reminds us of the NEIGHBOR function for the HP 71-B.

I have a 270.5 Byte programme which for real input returns both the upper & lower neighbours of input on the 50g.

Can anyone produce a shorter programme?

I'd LOVE to see your program. For years I've been living with this atrocity called NABR. It adds X ULPS onto Y. Example: 5 ENTER 2 NABR --> 5.00000000002

<< SWAP DUP XPON SWAP MANT .00000000001 4. ROLL * + SWAP ALOG * >>

Fails when Y=0, and gets the wrong answer for 1 ENTER -1 NABR.

(09-27-2017 07:39 AM)Joe Horn Wrote: [ -> ]I'd LOVE to see your program. For years I've been living with this atrocity called NABR. It adds X ULPS onto Y. Example: 5 ENTER 2 NABR --> 5.00000000002

<< SWAP DUP XPON SWAP MANT .00000000001 4. ROLL * + SWAP ALOG * >>

Fails when Y=0, and gets the wrong answer for 1 ENTER -1 NABR.

Doesn't work.

Edit: Does work.

(09-27-2017 07:39 AM)Joe Horn Wrote: [ -> ]I'd LOVE to see your program. For years I've been living with this atrocity called NABR. It adds X ULPS onto Y. Example: 5 ENTER 2 NABR --> 5.00000000002

<< SWAP DUP XPON SWAP MANT .00000000001 4. ROLL * + SWAP ALOG * >>

Fails when Y=0, and gets the wrong answer for 1 ENTER -1 NABR.

Very nice, could be the basis of an answer to my post.

(09-27-2017 07:52 AM)Gerald H Wrote: [ -> ]Very nice, could be the basis of an answer to my post.

After struggling with this, I gave up on it years ago. Please share your program. I'd love to see how you did it! Or is this a kind of mini-challenge? If so, I can't wait to see what folks here come up with!

Yes, I would very much appreciate contributions in the way of programmes or algorithms.

Your programme fails for input

-5

3

& will have to grow to accommodate negative reals.

I will certainly timely publish my programme but do not expect it to be the shortest.

I created this when Joe first mentioned the NEIGHBOR function.

It returns the next number larger than x=s*m*10^n

Basically, if x=0, return 1e-499

elsif s*m=-1, return (s.m + 1e-12)*10^n

else return (s.m + 1e-11)*10^n

Code:

`\<<`

IF DUP

THEN DUP XPON ALOG

ELSE 1E-488 END

SWAP OVER / @ 10^n s*m

DUP -1 \=/ 6 - 6 - ALOG + *

\>>

If I call this program NXT, then NEIGHBOR as defined in the 71 would be

Code:

`\<< IF OVER < THEN +/- NXT +/- ELSE NXT END \>>`

Cheers, Werner

Nice input Gerald and Joe!

I have a question though. From the other thread

Quote:NEIGHBOR(X,Y) [nearest machine-representable number to X in the direction of Y]

Wouldn't be Y representable by the system already? My doubt lies on the point that that the value given to the function is already a valid value for the system, so there is nothing to search.

Would be different with a string in input rather than a number.

(09-27-2017 11:22 AM)pier4r Wrote: [ -> ]I have a question though. From the other thread

Quote:NEIGHBOR(X,Y) [nearest machine-representable number to X in the direction of Y]

Wouldn't be Y representable by the system already? My doubt lies on the point that that the value given to the function is already a valid value for the system, so there is nothing to search.

Would be different with a string in input rather than a number.

Sorry, but I don't understand your question. The only thing that Y does is tell NEIGHBOR which direction to go. If Y>X, then NEIGHBOR(X,Y) returns the very next number GREATER than X which the HP-71 is capable of representing, and if Y<X then it returns the very next number LESS than X. The phrase "machine-representable number" means "limited to a 12-digit mantissa". The function has nothing to do with strings.

Examples:

NEIGHBOR(6,9) --> 6.00000000001 (the nearest machine-representable number

above 6)

NEIGHBOR(6,2) --> 5.99999999999 (the nearest machine-representable number

below 6)

Bravo Werner! I consider your contribution a complete solution & don't expect a shorter version (although "6 - 6 -" is ornate), would however be very pleased to see a more concise programme.

To keep my word & amuse Joe here's my version:

Edit: Corrected my programme to give correct result for zero. I have learned much from this thread, eg that .000000000001 is not the nearest representable number to zero.

I doubt that, given Werner's programme, anyone will now try this programme but the wrong result irritated me.

Code:

`::`

CK1&Dispatch

# FF

::

Z1_

FPTR2 ^RADDext

DUP

Z2_

FPTR2 ^RSUBext

;

BINT1

::

DUP%0=

casedrop

::

%MINREAL

DUP

%CHS

;

DUP

%SGN

SWAP

::

%ABS

DUP

%>%%

DO>STR

DUP

"E"

BINT1

POSCHR

DUPUNROT

2DUP

LAST$

3UNROLL

1_#1-SUB$

DUPLEN$

::

#1=case

::

".00000000001"

&$

SWAP&$

DOSTR>

SWAPDROP

;

ROTDUP

BINT14

#<>

ITE

::

BINT14

SWAP#-

ZERO_DO

CHR_0

>T$

LOOP

;

DROP

CHR_6

>T$

SWAP&$

DOSTR>

;

DUPDUP

4ROLL

DUP

%MANTISSA

%1

%=

case

::

2%>%%

%%-

DUP

%%10

%%/

%%+

SWAP

%>%%

SWAP

%%-

%%>%

;

%-

%2

%*

%-

;

ROT

%0>

?SEMI

%CHS

SWAP

%CHS

;

;

Which does have the advantage of giving no wrong answers, ie for input

9.99999999999E499

1

Joe's returns

9.99999999999E499

& for

9.99999999999E499

9.99999999999E499

Werner's returns

9.99999999999E499

while for

9.99999999999E499

my programme errors.

I can't believe the 50G doesn't have this function.

I'm confident it is present internally somewhere.

Pauli

Joe: what does NEIGHBOR return if X=Y?

Gerald:

(09-27-2017 11:53 AM)Gerald H Wrote: [ -> ]for

9.99999999999E499

9.99999999999E499

Werner's returns

9.99999999999E499

No, it errors out, as (for now) it considers it has to go up to the next number.

I guess your overflow flag is cleared, then it returns 9.99999999999e499

I'd say when X=Y the number should be returned unchanged, so:

Code:

`\<<`

IF DUP2 SAME THEN DROP

ELSE

IF OVER < THEN NEG NXT NEG ELSE NXT END

END

\>>

(09-27-2017 12:24 PM)Werner Wrote: [ -> ]Joe: what does NEIGHBOR return if X=Y?

Some interesting inputs & outputs on HP-71:

NEIGHBOR(7,7) --> 7

NEIGHBOR(0,0) --> 0

NEIGHBOR(0,7) --> 0.00000000001E-499 = MINREAL (non-normalized)

NEIGHBOR(1,0) --> 0.999999999999 (twelve 9's, not just eleven like my buggy program above)

Thanks, Joe

My program above returns correct results for all of these. The 1e-499 is normalized, though ;-)

Werner

(09-27-2017 11:51 AM)Joe Horn Wrote: [ -> ]Sorry, but I don't understand your question. The only thing that Y does is tell NEIGHBOR which direction to go. If Y>X, then NEIGHBOR(X,Y) returns the very next number GREATER than X which the HP-71 is capable of representing, and if Y<X then it returns the very next number LESS than X. The phrase "machine-representable number" means "limited to a 12-digit mantissa". The function has nothing to do with strings.

Examples:

NEIGHBOR(6,9) --> 6.00000000001 (the nearest machine-representable number above 6)

NEIGHBOR(6,2) --> 5.99999999999 (the nearest machine-representable number below 6)

Ah, ok, then I misunderstood. I thought the right function was like 'Y' is not representable by the system, can you give the closer number to Y, starting from X, that can represent Y?

Slow and simple, but it works. This just keeps adding or subtracting 10^n for successively larger values of n until X+10^n changes.

Code:

`@ NEIGHBOR`

@ Given X & Y (X on lvl2, Y on lvl1), find the next

@ number to X in the direction of Y that the calc can

@ represent. If X=Y then return X

«

OVER - SIGN @ X (-1,0,1)

1E-499 *

IF DUP THEN @ Special case for X==Y

WHILE DUP2 + PICK3 ==

REPEAT

10. *

END

END

+

»

Well done, David.

Gives wrong answer for input

1.E-499

6

returns

2.E-499

should be

1.00000000001E-499