6 ms·
Oddly enough I got an issue with float this week, 2 systems are communicating by transmitting float (rather needlessly I would add) and the conversion from floa
by seren 6y ago
Oddly enough I got an issue with float this week, 2 systems are communicating by transmitting float (rather needlessly I would add) and the conversion from float seems to be implemented differently on both systems, resulting in discrepancy sometimes.
This is kind of textbook example of an obvious bug but still surprising when you find it.
- enriquto 6y agoI do not understand what you mean. If you "convert" a float to a float it shouldn't change anything? As long as you keep to floats there should be no problem.
- nestorD 6y agoYou could run into problems with little endians and big endians if you do a binary tranfer or, more likely, have a lossy float->string->float conversion.
- enriquto 6y agoThat seems to be more a problem of strings that of floats, then.
- rini17 6y agoStrings have nothing to do with the issue that there is no widespread lossless text exchange format for FP. Instead we round FP numbers while encoding (like "0.3") and then "deround" it while decoding. (Lossless base10 encoding of 0.3 single precision would be like "10066330*2^-25"..not very readable).
- dahfizz 6y ago> the issue that there is no widespread lossless text exchange format for FP. If you have to use strings as the intermediate representation (why?) Then printf("%x") and scanf("%x") is perfectly lossless and widespread. The only thing that's lossy is converting floats to decimal point numbers, which is absolutely silly if it's just two machines communicating.
- dahfizz 6y agoUnless you are using an IBM mainframe, Big Endian is all but extinct. Besides, it is about ~10 lines of C to detect endianess and reorder bytes if necessary.
- pedrocr 6y ago> Besides, it is about ~10 lines of C to detect endianess and reorder bytes if necessary. Proper code to do this doesn't do any tests. Just grab the bytes from the order of the transfer format (in this case network order) into the order of the abstract machine in C. The compiler will turn that into whatever is needed depending on if it's compiling to a big-endian or little-endian machine and may use byteswap instructions if needed. Having tests in the code is a code smell that creates unchecked paths to the code that are much more likely to be wrong as they are not used most of the time.
- account42 6y ago> and may use byteswap instructions if needed Or it may not because often compilers fail to make simple optimizations: https://godbolt.org/z/NAt3uX https://godbolt.org/z/NAt3uX
- pedrocr 6y agoIt does fine if you actually write the correct code :) https://godbolt.org/z/qpLeWP https://godbolt.org/z/qpLeWP
- account42 6y agoThere is nothing incorrect about the code I posted - clang will compile it to a single read + bswap just fine. And you don't need to go that far back for your code to not be recognized - GCC 4.9 will produce individual loads and shifts for that too. The point is that you can't rely on compilers consistently to recognize complex patterns.
- 6y ago
- pjc50 6y agoRound-tripping floats through text is much, much harder to do than it sounds - you need to make sure you get all the decimal digits, and round in the correct way. e.g. https://randomascii.wordpress.com/2012/02/11/they-sure-look-equal/ https://randomascii.wordpress.com/2012/02/11/they-sure-look-...
- enriquto 6y agoI do not understand why would you ever round trip floats through text. That seems useless? In any case, if you really want to do that then you use a hexadecimal float representation (like C's printf has had the "%a" conversion since forever) , or simply print out the bytes. Representing a float in decimal is absolutely idiotic and the people who commit this atrocity and get into trouble for that have it coming.
- ColinWright 6y ago> I do not understand why would you ever round trip floats through text. There are many, many occasions in the real world where this is necessary ... I've dealt with it multiple times. When done carefully and with appropriate knowledge of the underlying systems it's not a problem. But just because you've never done, that doesn't mean it's the wrong thing to be doing. > if you really want to do that then you use a hexadecimal float representation There are combinations of systems where that won't work.
- pjc50 6y agoJSON? Human-readable representations in general? > Representing a float in decimal is absolutely idiotic Other way round: humans like decimal arithmetic, and will accept binary floating point as an intermediate representation.
- dahfizz 6y agoWe are talking about two machines talking to each other. Correctness is more important than human readability for bytes on a wire.
- ColinWright 6y agoI don't understand your confusion. Consider, system A has a float in memory, and wants to send it to system B. System A has no knowledge of how system B stores floats, whether it's big-endian or little-endian, how many bits of precision it uses, etc. It might also be that the only method of transmitting information is via a text encoding ... perhaps JSON, perhaps something else. So system A "prints" the float, converts it to a string, and sends that. It's even useful because it can be inspected "by eye" on the way through. Now system B receives the string and converts it to a float. All this sort of thing happens in the real world, and is sometimes dictated by the original designs of the system, and sometimes it's specified by customers that this is how it has to work. Does that help you to understand the original comment?
- MaxBarraclough 6y agoIt's not clear what 'conversion' is referring to here. Do you mean the communication is using a decimal representation (like JSON)?
- okennedy 6y agoEven without conversions floats cause problems. Several years back I was working on a SQL query transpiler, and was getting driven up the wall trying to explain why compiling query 6 from the TPC-H benchmark on some of our backends would agree with Postgres, and disagree on others. Worse, it worked perfectly on the OCaml backend, we used for debugging, but broke on our performance-focused C++ backend. I must have torn my hair out for nearly a week, but the culprit turned out to be TPC-H's defaults including a subtle and very hidden test for floating point numbers. Q6, with default values plugged in includes the bit: WHERE l_discount < 0.06+0.01 In the C++ backend (with a standard `float` iirc), 0.06+0.01 != 0.07, and the query result ended up wrong. Fun times. (I now occasionally toss Q6 in as a test query for my database class. Definitely teaches proper respect for floating point arithmetic :D)
- guenthert 6y agol_discount is not a monetary (fixed precision) type? It appears it ought to be, but I see now that is another can of worms ...