Finland holds Europe's largest civil defence exercise since WWII in preparation for an attack by Putin
War over our coastal paths! They've been loved by the public for generations for their bracing air and stunning views. But suddenly more and more are being fenced off by wealthy landowners whose message is effectively: PLEBS KEEP OUT
Migrant smugglers are using more and more 'mega-dinghies' to reach the UK because they have 'run out of small boats'
Terminated employee cost company hundreds of thousands of dollars because nobody revoked access
Instrument Clusters Are Now Paid Extras In Two Hyundai Models
Read more of this story at Slashdot.
Cruising into first class: The exclusive 'ship-within-a-ship' hiding INSIDE enormous vessels - with private pools, butlers and holidays for £6,000 a week
Tatler crowns the best private schools in Britain: Kate's alma mater, remote Scottish institution disliked by King Charles and 'Hippie Hogwarts' all make the list - as well as places boasting scuba diving lessons, an F1 simulator and 'no uniform'
Kemi vows to slash benefits bill to boost defence as she piles pressure on Burnham
To keep the AI hacking genie bottled up, try one-way networks
Ditch the overhead lighting - and 6 other swaps that will make any room in your house look instantly more expensive
CodeSOD: Heating Up
A common option for retrofitting heating and cooling into older homes is a mini-split, frequently tied to a heat pump. They're (relatively) cheap to install, energy efficient, and can be added without substantial modifications to the home. They also, annoyingly, are mostly controlled via IR remotes, making them challenging to wire up to home automation or even a household thermostat.
People have made solutions, and today's code comes from one of those solutions. Which, I want to stress, this code comes from an open source project for home automation, so it's not the code that's wrong, here. At first I thought it was, and had a moment of, "I'm not going to pick on some hobby project," but then I realised the hobby project points at a deeper issue.
// temperature helper these are direct mappings based on the remote float toFahrenheit(float fromCelsius) { // Lookup table for specific mappings const std::map<float, int> lookupTable = { {16.0, 61}, {16.5, 62}, {17.0, 63}, {17.5, 64}, {18.0, 65}, {18.5, 66}, {19.0, 67}, {20.0, 68}, {21.0, 69}, {21.5, 70}, {22.0, 71}, {22.5, 72}, {23.0, 73}, {23.5, 74}, {24.0, 75}, {24.5, 76}, {25.0, 77}, {25.5, 78}, {26.0, 79}, {26.5, 80}, {27.0, 81}, {27.5, 82}, {28.0, 83}, {28.5, 84}, {29.0, 85}, {29.5, 86}, {30.0, 87}, {30.5, 88} }; // Check if the input is in the lookup table auto it = lookupTable.find(fromCelsius); if (it != lookupTable.end()) { return it->second; } // Default conversion and rounding to nearest integer return roundf(fromCelsius * 1.8 + 32.0); }Okay, I am going to pick on their code a little bit; using float as a key in a map is asking for trouble, because rounding errors are going to surprise you. But honestly, failing to find the key you're looking for is better than the opposite, since that actually does the correct thing. Because if you look carefully at the table, you'll see that it's wrong.
18C, for example, should be 64F. Well, 64.4F, but we're rounding to an integer. The choice here is to roughly map every 0.5C increase to a 1F increase, which is not the conversion factor. They try and correct- note how the table mostly steps by 0.5C, but skips 19.5C.
The opposite direction is similarly bad:
// temperature helper these are direct mappings based on the remote float toCelsius(float fromFahrenheit) { // Lookup table for specific mappings const std::map<int, float> lookupTable = { {61, 16.0}, {62, 16.5}, {63, 17.0}, {64, 17.5}, {65, 18.0}, {66, 18.5}, {67, 19.0}, {68, 20.0}, {69, 21.0}, {70, 21.5}, {71, 22.0}, {72, 22.5}, {73, 23.0}, {74, 23.5}, {75, 24.0}, {76, 24.5}, {77, 25.0}, {78, 25.5}, {79, 26.0}, {80, 26.5}, {81, 27.0}, {82, 27.5}, {83, 28.0}, {84, 28.5}, {85, 29.0}, {86, 29.5}, {87, 30.0}, {88, 30.5} }; // Check if the input is in the lookup table auto it = lookupTable.find(static_cast<int>(fromFahrenheit)); if (it != lookupTable.end()) { return it->second; } // Default conversion and rounding to nearest 0.5 return roundf((fromFahrenheit - 32.0) / 1.8 * 2) / 2.0; }Here, we can be off by as much as a 1C, which is certainly a noticeable feeling.
At first glance, I thought this was just a misguided attempt at optimizing the lookup. For common values, do a lookup instead of calculating because it's faster. Seems like the kind of mistake a hobby project might make, and definitely not a WTF. But it's the comment which corrects me: these are direct mappings based on the remote.
These remotes usually have a display. So when you see on the remote that you're trying to set the temperature to a comfortable 72F, the remote is actually sending 22.5C to the unit. That's the actual temperature being sent.
Now, why on Earth does the remote behave this way? Well, I haven't cracked one open to read off the part numbers, but I'm going to go out on a limb and guess that the microcontoller in the remote doesn't handle floating point operations all that well. So it almost certainly does use a lookup table to decide what signal to send, and the lookup table is populated by "good enough" approximations of temperature conversions. There aren't a lot of places that use Fahrenheit, so being "close enough" is a reasonable solution. If you want accurate temperatures, use SI units, not "freedom units".
In the end, I'd say that neither the hobby project, nor the remote control are the WTF here; locales that insist on using weird ass units are.
.comment { border: none }