H>HMS conversion HP15C vs. HP42S vs HP67

09072018, 09:43 AM
Post: #21




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09062018 05:31 PM)Dieter Wrote: EDIT AND UPDATE: Yet Free42 binary (of which I must be the only user?) gets it right ;) Werner 41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L 

09072018, 02:40 PM
Post: #22




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09072018 09:43 AM)Werner Wrote:(09062018 05:31 PM)Dieter Wrote: it looks like the usual binary roundoff problem. The approach I chose for >HR for the binary version is robust but not very pretty: multiply x by 1e12, round to nearest integer, and then do everything using integer math. Plus, there is a special case in for x < 0.01, where the conversion reduces to a simple division by 0.36. The idea was to make sure that it will never get anything wrong that the HP42S gets right, but the simplistic approach I chose does mean a bit of precision is lost. If someone has a better algorithm lying around for IEEE754 double precision binary, I would be interested. 

09072018, 03:43 PM
Post: #23




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09072018 07:07 AM)Pekis Wrote: And with my funny oneliners: Hi, Pekis Above work (mostly) in Excel, because Excel does some behindthescene rounding. Example: if angle = 2° 1' , X = 2.01 (IEEE double of 2.0099999...) DMS>DEG formula: Python: (502.499999...  200  120) / 90 = 2.0277777... (wrong!) Excel : (502.5  201  120) / 90 = 2.0166666... (all terms rounded implicitly) I would rather do explicit scaling / rounding, before conversion (see post #17): X = 2.0099999 ... > Y = 20100.00 (scaled and rounded to hundredth of second) DMS>DEG: (Y  40*int(Y/100)  2400*int(Y/10000)) / 3600 = (20100  8040  4800) / 3600 ~ 2.0166666... 

09072018, 04:57 PM
(This post was last modified: 09072018 04:57 PM by AndiGer.)
Post: #24




RE: H>HMS conversion HP15C vs. HP42S vs HP67
Retro15C has funny results ...
Any positive integer.38 yields in positive integer.6444... 0.38 yields in 0.6333... 0.30 yields in  no not in 0.5  but (+)0.1666... 

09072018, 08:49 PM
Post: #25




RE: H>HMS conversion HP15C vs. HP42S vs HP67
Think I'm not using that one any longer.


09072018, 09:42 PM
Post: #26




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09062018 10:37 PM)Thomas Okken Wrote: I'm guessing there's a typo in his post, because it seems unlikely anyone would mistype the actual test case three times! Thanks for all the testing and detailed replies. I am sorry to have added some confusion in my OP which indeed contained a typo. Free42 and Legendary67 returned the same result as Excel, i.e. 146:54:24 (not 44). So Retro15C is the culprit. 

09082018, 12:59 PM
(This post was last modified: 09082018 01:10 PM by Albert Chan.)
Post: #27




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09072018 02:40 PM)Thomas Okken Wrote: The approach I chose for >HR for the binary version is robust but not very pretty: multiply x by 1e12, Hi, Thomas Okken Just a crazy example, billion degrees 4 minutes. X = 1000000000.03999996185 ... (binary float) X * 1e12 = 1000000000039999897600 (binary, exact integer) With this value, result will be overcounted ~ 100  60 = 40 seconds (just like Retro12C) (note: this is only based on your comment, I have not try it on the actual emulator) Instead of nearest integer, it might be better with rounded 12 digits value (no scaling needed). 12 digits can safely pushed to 15, see https://www.exploringbinary.com/numbero...nversions/ For accurate dtoa, David Gay's dtoa.c is well tested: http://www.netlib.org/fp/dtoa.c Or, you can try my code: https://github.com/achan001/dtoafast Edit: some good C compiler can do correct strtod and dtoa functions. With those, above code is not needed 

09082018, 02:35 PM
(This post was last modified: 09082018 02:45 PM by Thomas Okken.)
Post: #28




RE: H>HMS conversion HP15C vs. HP42S vs HP67
It doesn't multiply the entire number by 10^12, just the fractional part. But, yes, with a case like that, numerical cancellation will cause the binary roundoff to mess up the result. Avoiding that is possible but ugly (I think the 33S does this).
This is why Free42 Decimal exists. UPDATE: Hadn't read your post carefully enough. Better binarytodecimal does sound like a good idea. I'll look into it sometime after my vacation... 

09082018, 03:45 PM
Post: #29




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09082018 02:35 PM)Thomas Okken Wrote: It doesn't multiply the entire number by 10^12, just the fractional part. But, yes, with a case like that, numerical cancellation will cause the binary roundoff to mess up the result. Avoiding that is possible but ugly (I think the 33S does this). I thought of that (scale only fractional part) before posting. But, whether or not the integer part got removed before scaling does not matter: X  INT(X) is exact = 0.03999996185 ... (DMS>DEG overcounted 40 seconds still here) In fact, my suggestion of rounded 15 digits required INT(X) not to be removed. Rounded X (to 15 digits) = "1000000000.04" (character string) 

09082018, 06:03 PM
(This post was last modified: 09082018 06:08 PM by Albert Chan.)
Post: #30




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09072018 03:43 PM)Albert Chan Wrote: Example: if angle = 2° 1' , X = 2.01 (IEEE double of 2.0099999...) Uh, I was getting stupid ... My post #23 already have an elegant method. Scale by 10000 (to move the troublesome decimal point), then round to 15 digits. (approximated rounding good enough, just to catch the "40 seconds" bug) That is all that is needed. No reason to get precisely rounded 15 digits decimal. 

09092018, 04:21 AM
Post: #31




RE: H>HMS conversion HP15C vs. HP42S vs HP67
Just think of a great idea: fast, simple, accurate DMS>DEG
The whole point of scaling / rounding is to avoid the "40 seconds" bug. All we need is to give up 1 ULP binary float accuracy, and we are safe. (correct strtod conversion guaranteed max error <= 0.5 ULP) Using this thread original example, X = 183.3799999 ... X = nextafter(X, X+X) = 183.38000000000002387 ... Now, safe to apply Pekis DMS>DEG formula, and we are done (09072018 07:07 AM)Pekis Wrote: And with my funny oneliners: 

09092018, 05:10 AM
Post: #32




RE: H>HMS conversion HP15C vs. HP42S vs HP67
Unfortunately Pekis' HMS formula suffers from the "60 second bug" which several HP's also suffered from. If you input 9.99999999999 (12 digits total) into any 12digit HP, and run Pekis' HMS formula, you get exactly 9:59:60 as the result. Should be 9:59:59.9999999 of course.
<0ɸ0> Joe 

09092018, 05:29 AM
Post: #33




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09092018 05:10 AM)Joe Horn Wrote: Unfortunately Pekis' HMS formula suffers from the "60 second bug" which several HP's also suffered from. If you input 9.99999999999 (12 digits total) into any 12digit HP, and run Pekis' HMS formula, you get exactly 9:59:60 as the result. Should be 9:59:59.9999999 of course. The way I see it is that it is more of an "error" of the calculator limited precision. If the calculator had a higher precision, it would certainly return the correct answer with the right amount of 9's trailing at the end of it. 

09092018, 06:13 AM
(This post was last modified: 09132018 02:43 PM by Albert Chan.)
Post: #34




RE: H>HMS conversion HP15C vs. HP42S vs HP67
Hi, Joe Horn
I was in the middle of removing Pekins formula ... DMS>DEG may have problems too, with INT(100*X) Doing conversion with integer degree and minutes is safer (float seconds OK): Y = 100*X Y = nextafter(Y, Y + Y) DMS>DEG = (2.5*Y  int(Y)  60*int(Y/100)) / 90 Max error = decimal to binary error + scaling error = 0.5 + 0.5 = 1.0 ULP > 1 ULP is enough to get to safety, away from "40 seconds bug" Edit: conclusion is correct, but ULP math was wrong, see post 55 

09092018, 07:50 AM
Post: #35




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09092018 05:10 AM)Joe Horn Wrote: Unfortunately Pekis' HMS formula suffers from the "60 second bug" which several HP's also suffered from. If you input 9.99999999999 (12 digits total) into any 12digit HP, and run Pekis' HMS formula, you get exactly 9:59:60 as the result. Should be 9:59:59.9999999 of course. Hi, Joe! 9.99999999999 >HMS is 9:59:59.999999964, exactly, and so the rounded 12digit answer should be 10:00:00, which is what the 48G gets. Unless you meant that Pekis' formula should have returned either 10 or 9:59:59.9999999 Cheers, Werner 41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L 

09092018, 08:51 AM
(This post was last modified: 09092018 08:52 AM by Werner.)
Post: #36




RE: H>HMS conversion HP15C vs. HP42S vs HP67
A better HMS formula, courtesy of John H. Meyers in comp.sys.hp48, long ago:
H.MS=H.FP(H.)*0.4FP((H.FP(H.)*0.4)*100)*0.004 or T := H. FP(H.)*0.4 ; H.MS := T  FP(T*100)*0.004 ; translated into RPN that would be ENTER FRC .4 x  1E4 % FRC 4E3 x  At least, it returns 9.59599999999 for 9.99999999999 .. There's an equivalent HR formula: H.=H.MS+FP(H.MS*100)/150+FP(H.MS+FP(H.MS*100)/150)/1.5 or T := H.MS + FP(H.MS*100)/150; H. := T + FP(T)/1.5; Cheers, Werner 41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L 

09092018, 08:59 AM
Post: #37




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09092018 05:10 AM)Joe Horn Wrote: Unfortunately Pekis' HMS formula suffers from the "60 second bug" which several HP's also suffered from. If you input 9.99999999999 (12 digits total) into any 12digit HP, and run Pekis' HMS formula, you get exactly 9:59:60 as the result. Should be 9:59:59.9999999 of course. The HP67 gives 9.5959999999 in DSP 9 mode 9.5960 in DSP 4 mode 9.60 in DSP2 mode 10 in DSP 0 mode It is just following its normal display rounding code. In this case, it doesn't know that certain digits are hours, minutes, or seconds. cheers Tony 

09092018, 11:39 AM
(This post was last modified: 09142018 02:12 PM by Albert Chan.)
Post: #38




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09092018 06:13 AM)Albert Chan Wrote: Y = 100*X Above can be simplified and maybe more accurate by using noninteger factors Y = 100.00000000000001 * X DMS>DEG = (2.5*Y  int(Y)  60*int(Y/100)) * 0.011111111111111108 first factor (with 15 zeroes) = 100.000 ... = 1 ULP above 100.0, to fix "40 seconds" bug second factor (with 15 ones) = 0.01111... = 2 ULP below 1/90.0, to compensate overestimation For angle=183°38' , above produce error of +0.73 ULP (against exact 183 + 38/60) For 1000000000°4', above produce error of +0.47 ULP ... not too bad. 

09092018, 01:54 PM
(This post was last modified: 09092018 01:59 PM by Thomas Okken.)
Post: #39




RE: H>HMS conversion HP15C vs. HP42S vs HP67
The problem with using nextafter() is that the closest decimal equivalent isn't always going to be higher. In other words, you're always rounding up, but sometimes 0.3999 really is 0.3999, not a mangled 0.4000.
How about this: instead of multiplying by 10^12, I'll multiply by whichever power of 10 makes the integral part of the number have 12 digits (or 15, or whatever choice is safe), then round to the nearest integer, then remove what was originally the integer part, and finally normalize the scale of the remainder. That should preserve the nice properties of the current Free42 Binary implementation, while improving its handling of binary roundoff as much as possible (without doing the equivalent of a fullblown dtoa(), anyway). 

09092018, 03:25 PM
(This post was last modified: 09142018 02:31 PM by Albert Chan.)
Post: #40




RE: H>HMS conversion HP15C vs. HP42S vs HP67
(09092018 01:54 PM)Thomas Okken Wrote: The problem with using nextafter() is that the closest decimal equivalent isn't always going to be higher. In other words, you're always rounding up, but sometimes 0.3999 really is 0.3999, not a mangled 0.4000. Please see my previous post #38. I decided not to do nextafter(), saving a step. Always roundingup also have a compensating always roundingdown. Anyway, we are talking 1 ULP adjustment, not thousands (rounding to 12 digits). The effect is so tiny (just enough to avoid the bug), you barely see it: X = 0.3998999 ... (39 minutes, 99 seconds) Y = X * 100.00000000000001 = 39.9900000000000019 ... ~ 39.99 (still 99 seconds) DMS>DEG = 0.6774999999999999 (1.08 ULP below exact 39/60 + 99/3600) X = 0.4699999 ... (47 minutes, but possible "40 seconds" bug) Y = 47.000000000000007 ... DMS>DEG = 0.7833333333333333 (0.07 ULP below exact 47/60) Even if user input is 0.46999 99999 99999 8, above code still intepret it as 46 minutes 100 seconds. So, no worries about misintepreting user input, 0.3999 will not mangled to 0.4000 Last 8 changed to 9 will confuse it (as 47 minutes). But, you are now reaching beyond IEEE double ... 

« Next Oldest  Next Newest »

User(s) browsing this thread: