1

I have recently learned about fixed-sized integer and am planning to use them in an old program I wrote years ago.

Is there any equivalent of fixed-sized int for float and/or double?

My plan is to use "native types" int,float,double for the biggest part of the program and only specify fixed-size types when portability is a concern (like read/write with a binary file). I use a binary file store data like: date yyyymmdd (so uint32), flags [0,4] (so uint8), string (null terminated string) and currencies (now it's double).

Concerning portability, the program is "portable" is the sense that it can be compiled (or cross-compiled) and run on different platform. So far: linux, windows, android (natively, through a terminal emulator without GUI) and OpenBSD (strcat/strcpy only needs to be replaced by strlcat/strlcpy in 2 lines). I am concerned about what could happen to the stored float/double if I used the same binary data file between linux x86_64, android arm-something, windows 32 something, etc... I would like to have a way to enforce a unique size and representation of floating-point values in the binary file.

funkygoby
  • 13
  • 6
  • If `__STDC_IEC_559__` is defined, then yes, else no. Need more details on your FP portability requirements. Loosely: recommend store currencies as a string. – chux - Reinstate Monica Oct 14 '16 at 15:01
  • The IEEE standard for floating point is ubiquitous today, except in some very cheap embedded processors. Since you are reading a file you can ignore them. What you can't completely ignore is byte-order (aka endiness), that's a problem with your fixed-size integers as well. – Hans Passant Oct 14 '16 at 15:25
  • @chux: Post edited for clarity about portability. – funkygoby Oct 15 '16 at 11:32
  • @Hans Passant: I never though about endiness. I am considering storing data in a plain text file now... – funkygoby Oct 15 '16 at 11:34
  • Would [my answer](http://stackoverflow.com/a/14955046/968261) to a related question help? – Alexey Frunze Oct 15 '16 at 11:47
  • @AlexeyFrunze It helped me discover the idea behind float representation wich comfort me in using simple string or a text file. – funkygoby Oct 16 '16 at 17:18

2 Answers2

1

For currencies, suggests special handling. Select a fixed width integer type to meet range needs (int64_t or int32_t) and scale by smallest monetary unit. If code is only storing/reading values like 123.12

void Store_int32(int32_t x); // Handles int32_t in endian independent method
int32_t Get_int32(void);     // Handles int32_t in endian independent method

void Store_Currency(double c) {
  if (c < INT32_MIN/100.0 || c > INT32_MAX/100.0) Handle_RangeError();
  Store_int32(round(c*100.0));
}

double Get_Currency(void) {
  Get_int32()/100.0;
}

For general use of double, use conversion to/from a textual hexadecimal (or decimal with sufficient precision) FP notation.

void Store_double(double c) {
  char s[100];
  sprintf(s, "%a", c);                         // 0x1.ec7ae147ae148p+6
  // or
  sprintf(s, "%.*e", DBL_DECIMAL_DIG - 1, c);  // 1.2312000000000000e+02
  Store_string(s);
}

double Get_double(void) {
  char s[100];
  Get_string(s, sizeof s);
  double x;
  sscanf(s, "%f", &x);  // %f reads decimal and hexadecimal FP formats.
  return x;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Most floating point is IEEE 754, 64 bit or 32 bit. However if the floating point unit in your processor is not compatible, there's no realistic, efficient way of making it compatible, and thus programs will produce slightly different results when run on different machines. (That's actually a good test for a sound program - if results are significantly different because of floating point errors, then you are handling floating point operations badly).

You can however load and save the closest representation to IEEE 754 in a binary file, portably. Code is maintained here here

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
  • 1
    If the host computer **is** using a nonstandard floating-point format, then the repeated rounding error introduced by this instruction can make the result terrible. https://github.com/MalcolmMcLean/ieee754/blob/6b8baa361519162bd4250dbf44f9ee7869f96506/ieee754.c#L66 It would be much better to compute with integers, for which as the question points out, there are fixed-size definitions in `stdint.h` that will work as expected on any compliant platform, than to rely on the very type that is assumed not to be reliable. – Pascal Cuoq Oct 14 '16 at 17:17
  • @Pascal Cuoq: That's in the case of scientific calculation right? In my case, I am only storing short decimals: *123.12* – funkygoby Oct 15 '16 at 11:36
  • It depends if your FPU can represent 0.5, 0.25 and so on exactly. If not there could be a serious accumulation of error. Decimals can't be exactly represented in binary-point floating point, but the error is unlikely to matter if you only want 5 decimal places. – Malcolm McLean Oct 15 '16 at 12:00
  • In my case, standard cpu I guess. Your answer answer my question but I discovered that my problem is also about endiness. – funkygoby Oct 16 '16 at 17:20