1

We have a TCP/IP socket software including a Java client and C++ server. The data across the socket contains numbers, int, float, and char array. The precision of these floats are four digits after the point. Recently, we started to use either char array to represent float in data structure/protocol or int to represent float (float to int by time 10000 and then divide 10000 on receiver side) because of the precision.

I was told it is difficulty to keep the precision if we use float inside the data structure/protocol directly. The sender is hard to put exactly float into the socket and the receiver is hard to receive/convert back to the exact float number.

I am not convinced. By reading the Wiki again. It seems the single-precision float can provide 6-9 precision:

This gives from 6 to 9 significant decimal digits precision (if a decimal string with at most 6 significant decimal is converted to IEEE 754 single precision and then converted back to the same number of significant decimal, then the final string should match the original; and if an IEEE 754 single precision is converted to a decimal string with at least 9 significant decimal and then converted back to single, then the final number must match the original [3]).

What's the good practice to transfer float across the internet if the required precision is 4 or 6? How about more than that? Double!?. How banks handle bigger floating point numbers?

Community
  • 1
  • 1
5YrsLaterDBA
  • 29,380
  • 38
  • 121
  • 200
  • 3
    Don't send floats in the first place. Send instead an integral representation of a decimal value. Perhaps one int for a whole number and a second int for a factor of 10. If the precision is always 4 (or 6) decimals, then you can simply send a single int and state in the spec that there are 4 (or 6) implied decimals. – John Dibling May 21 '13 at 16:17
  • http://stackoverflow.com/questions/10895243/printing-float-preserving-precision?rq=1 – Brian Roach May 21 '13 at 16:18
  • These 6-9 digits are the *sum* of the number of digits *before* (left of) and *after* (right of) the decimal point, so if you actually need 4 digits after the decimal point, worst case you'll only be able to encode numbers up to 99.xxxx using single precision floats ... – fvu May 21 '13 at 16:20
  • 2
    banks do not use float and double values because they are not accurate, BigDecimal handles currency values much better – hoaz May 21 '13 at 16:24
  • On the other hand, why don't you switch to some ready-made serialization solution that's cross-language and well maintained like [Google's protobuf](http://code.google.com/p/protobuf/)? It already [supports 15 scalar datatypes out of the box](https://developers.google.com/protocol-buffers/docs/proto#scalar). It will save you some headache now and will prove to be easier to maintain and extend in the long run? – fvu May 21 '13 at 16:29
  • 2
    I don't work with banks, but I do work in trading. No financial exchange I've ever developed for sends `float`s on the wire. – John Dibling May 21 '13 at 16:29

2 Answers2

1

Have you looked at google protocol buffers? https://code.google.com/p/protobuf/

Basically, you would use protobuf to serialize the float to a string, send the string over the network, and use protobuf on the other side to turn it back into a float. While you're at it you can send the rest of the message as a string with protobuf as well to enforce some structure/consistency in the data you send.

Additionally, the encoded message is language independent, so any language that has a protocol buffer library (google provides c++, python, and java implementations, and there are countless third-party implementations for other languages) can read/parse/use that message.

Elliott
  • 1,288
  • 1
  • 13
  • 24
  • This doesn't address and cannot solve the issue raised in the question. – user207421 May 21 '13 at 21:59
  • "What's the good practice to transfer float across the internet if the required precision is 4 or 6?" My answer looks relevant to me. – Elliott May 22 '13 at 17:48
  • An answer that doesn't even contain the words 'floating point' or 'precision' cannot possibly address a question about floating point precision. And you've failed to spot the underlying fallacy. – user207421 May 23 '13 at 00:16
  • Your comment would be a lot more helpful if you said what the "underlying fallacy" was instead of waiting for me to ask. – Elliott May 23 '13 at 01:22
  • The underlying fallacy is addressed in my answer. It would be a lot more helpful if you read it, instead of waiting for me to repeat it here. – user207421 May 23 '13 at 10:46
1

The precision of these floats are four digits after the point.

No it isn't. Your floats do not have 'four [decimal] digits after the [decimal] point' at all. They have an unknown number of binary digits, which you cannot control. All your multiplying and dividing by 10000 doesn't and cannot change that, because decimal places and binary places are incommensurable. If you want a fixed decimal precision you must use a decimal radix.

Recently, we started to use either char array to represent float in data structure/protocol or int to represent float (float to int by time 10000 and then divide 10000 on receiver side) because of the precision.

A complete waste of your time. See above. See also here for proof.

I was told it is difficult to keep the precision if we use float inside the data structure/protocol directly. The sender is hard to put exactly float into the socket and the receiver is hard to receive/convert back to the exact float number.

You were misinformed. You can put the float directly onto the wire in its binary, format and recover it identically, using the API of DataOutputStream and DataInoutStream. However you shouldn't be using floating-point at all.

What's the good practice to transfer float across the internet if the required precision is 4 or 6?

The question embodies a contradiction in terms.

How banks handle bigger floating point numbers?

They don't use them.

Community
  • 1
  • 1
user207421
  • 289,834
  • 37
  • 266
  • 440