Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compact lossless representation of floating point constants in C/C++

I have a program written in C++ which is generating C source code for mathematical calculations. I have noticed that the constants take up very much space in the generated code and am looking for a more compact representation.

To generate constants, I am now using:

double v = ...
cfile << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;

I am pretty sure that this is a lossless representation, but it is also very bloated. For example a zero and a one would be represented as something like 0.0000000000000000e+00 and 1.0000000000000000e+00. And "0." or "1." carries just as much information.

Is there a way to print constants to file in a more compact, but still lossless manner? It does not need to look good for a human reader, just compile when present in plain C code (if C99, I would prefer if it's also valid C++). Hexadecimal could be ok if it is portable.

EDIT: Removed std::fixed in code snippet.

like image 577
Joel Avatar asked Mar 01 '13 11:03

Joel


1 Answers

You can use hexadecimal floating point (The format specifier %a for printf() in C); it's defined to preserve all bits of precision (C11, 7.21.6.1p8, a,A specifiers).

cfile << std::hexfloat << v;

If your compiler/standard library doesn't support hexfloat, you can use C99 %a printf specifier (this is equivalent, as specified in C++11 table 88 under section 22.4.2.2.2):

printf("%a", v);

For example, the following program is valid C99:

#include <stdio.h>
int main() {
   double v = 0x1.8p+1;
   printf("%a\n", v);
}

Your generated source file will not be valid C++11 as rather absurdly C++11 does not support hexadecimal floating point literals. However many C++11 compilers support C99 hexadecimal floating point literals as an extension.

like image 55
ecatmur Avatar answered Sep 22 '22 11:09

ecatmur