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