Steve's Programming Challenge: Weights and Measures - Printable Version +- QB64 Phoenix Edition (https://qb64phoenix.com/forum) +-- Forum: Chatting and Socializing (https://qb64phoenix.com/forum/forumdisplay.php?fid=11) +--- Forum: General Discussion (https://qb64phoenix.com/forum/forumdisplay.php?fid=2) +--- Thread: Steve's Programming Challenge: Weights and Measures (/showthread.php?tid=2949) |
Steve's Programming Challenge: Weights and Measures - SMcNeill - 08-15-2024 So here's a challenge which I'd like to propose for all of our coders here to undertake -- particularly @TerryRitchie @bplus @Pete @Dav , but which I'd truly LOVE to see everyone tackle. The program concept is very simple -- Write a program that simulates you being a merchant in ancient times. You have a whole bunch of lead weights, which you can use to measure out how much a customer's gold nugget weighs. Your available weights are all in the power of two -- you have: 1 four-pound weight. 1 two-pound weight. 1 one-pound weight. 1 half-pound weight. 1 quarter-pound weight. 1 1/8-pound weight. And so on to give you one of each weight from 4 pounds to 1/256 pounds. Now the task is to figure out what weights are required to properly and perfectly weigh the following: A 3 pound gold nugget A 3/8 pound gold nugget A 11/32 pound gold nugget A 1/10 pound gold nugget Now the first solution is obviously 1 2-pound weight + 1 1-pound weight. The question is -- can you find the proper combination for the other three nuggets I've mentioned?? Complete this task, and I doubt you guys will ever have any question ever again in the future about how floating point numbers work. As you're some of our most prolific posters (and teachers) here, I would hope a simple task like this would be enough to help you guys understand the underlying issue with floating point numbers, so when people ask in the future, you'll be able to explain it to them better. RE: Steve's Programming Challenge: Weights and Measures - Pete - 08-15-2024 My father owned an Italian Deli when I was a kid. This reminds me of the time I was taking my first algebra class in junior high school, and I asked him... Ham is $1.50 a pound, Cheese is $1.00 a pound, and roast beef is $2.50 a pound. If a man walks into your store and has $20 to spend and he wants twice as much roast beef as ham but half as much cheese as roast beef and wants to know how much roast beef, ham, and cheese he will get for $20, what do you tell him? My Dad's reply was: "I'd tell him to get the hell out of my store!" Pete RE: Steve's Programming Challenge: Weights and Measures - SMcNeill - 08-16-2024 (08-15-2024, 11:49 PM)Pete Wrote: My father owned an Italian Deli when I was a kid. This reminds me of the time I was taking my first algebra class in junior high school, and I asked him... The trick here is to show the impossibility of the answer. All weights can be described in relation to the smallest one: 1/256 weight = 1 of the smallest (1/256) 1/128 weight = 2 of the smallest (2/256) 1/64 weight = 4 of the smallest (4/256) ..see where I'm going with this here? Now, 11/32 can also be represented in relation to that smallest size. 11/32 = 88/256. As 88 is a whole number, we can pick out whole number combinations to match that. a 1/4 weight (8/32) + a 1/16 weight (2/32) + a 1/32 weight = 11/32... Perfect match. The problem comes when you get to the 1/10 pound nugget. That's 25.6/256... Our values only represent WHOLE numbers. We might move the scales to 25/256, or over to 26/256, but it's *IMPOSSIBLE* to get 25.6/256 pounds. It's the inherent limit of binary math and floating point numbers. It's literally IMPOSSIBLE to perfectly represent some values. You can divide your weights in half until they're on the atomic level, and... you're still not going to get 1/10 represented perfectly. An exercise like this is the perfect way for folks to visualize what's going on under the hood with floating point values. RE: Steve's Programming Challenge: Weights and Measures - SMcNeill - 08-16-2024 (08-15-2024, 11:49 PM)Pete Wrote: My father owned an Italian Deli when I was a kid. This reminds me of the time I was taking my first algebra class in junior high school, and I asked him... Your story of your dad also reminds me of one my own father used to tell years ago. One of the nearby neighbors had 3 sons and 17 horses. When he passed away, the will read: "I want to give my oldest son 1/2 of my horses, my middle son 1/3 of my horses and my youngest son 1/9 of my horses." The family had no idea how to handle such a situation, so they asked my grandfather for help. He thought on the issue that night, went to bed, and rode over the next morning on his old horse and gave it to the family as a funeral present. Now, it wasn't so hard to sort out what to do: The oldest got 1/2 of 18, which was 9 horses. The middle child got 1/3 of 18, which was 6 horses. The youngest child got 1/9 of 18, which was 2 horses. And the horse left over, my grandfather claimed for himself, as fee for solving their problem, as he rode back home later that morning on the same horse which he rode in on. RE: Steve's Programming Challenge: Weights and Measures - Pete - 08-16-2024 I tried that puzzle using donkeys but the best I could come up with was a 1/2 ass solution. Okay, I'll tackle the middle 2.... 1/4 + 1/8 = 3/8 1/4 + 1/16 + 1/32 = 11/32 Pete RE: Steve's Programming Challenge: Weights and Measures - dano - 08-16-2024 I wrote my program to check all combinations of the above and discovered that the .1 LB could get close, but not exact: Code: (Select All)
RE: Steve's Programming Challenge: Weights and Measures - SMcNeill - 08-16-2024 (08-16-2024, 12:24 AM)dano Wrote: I wrote my program to check all combinations of the above and discovered that the .1 LB could get close, but not exact: Exactly. And that's the error which we see in floating point math. We can get close to representing some values, but never exact. That *close but not exact* is the cause of floating point errors that we see when doing math. It's simply impossible to perfectly represent some values in binary-numbers, just as it's impossible to perfectly represent some numbers in standard base-10 values. What is 1/3 as a decimal? 0.33333333333333333333333333333333333333333333333333333333333(keep holding down that 3 key... you haven't got it perfect yet...) We can't perfectly represent 1/3 in decimal. We also can't perfectly represent 1/10 in binary. We get "close, but not exact", and that "close" is where our math errors and rounding errors occur over time in our programs. RE: Steve's Programming Challenge: Weights and Measures - Pete - 08-16-2024 When I was working out calculations in string math, I simply kept my calculator tracking in fractions, instead of decimals. That allowed for reverse calculations to get back to 1, instead of .9999999999999999999 and so on. Pete RE: Steve's Programming Challenge: Weights and Measures - Jack - 08-16-2024 Steve, I agree with you but most of the time floating-point math works surprisingly well, but then you have cases where it fails catastrophically RE: Steve's Programming Challenge: Weights and Measures - SMcNeill - 08-16-2024 (08-16-2024, 12:52 AM)Jack Wrote: Steve, I agree with you but most of the time floating-point math works surprisingly well, but then you have cases where it fails catastrophically Aye. Folks just need to realize *WHY* it tends to fail, when it does. FOR i = 1 TO 100 STEP 0.1 PRINT i NEXT ^That's *going* to have issues in it, just for the simple fact that we're adding 0.1 -- a number we can't represent perfectly -- over and over in that loop, which compounds the level of error until it's quite noticeable. It's not a flaw in QB64. It's not a glitch in the matrix. There's no "Fix" for it. That's just life with floating point values. They're fast -- but they're imprecise. If one needs precision, use integer values (Loop from 10 to 1000 and divide by 10). It's why banks track money by pennies and not dollars. You have 12345 pennies in the bank, not $123.45 dollars. The dollars is just formatted at the PRINT end, to make it easier for people to understand and relate to. Internally, it's all pennies. |