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

I have a program written in C ++ that generates C source code for mathematical calculations. I noticed that constants take up a lot of space in the generated code and are looking for a more compact representation.

To generate constants, I now use:

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

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

Is there a way to print constants for a file in a more compact but lossless way? It doesn’t need to look good for a human reader, just compile it if it is present in simple C code (if C99, I would prefer it to be also valid C ++). Hexadecimal may be ok if it is portable.

EDIT: Removed std::fixedin code snippet.

+5
source share
4 answers

This is not a problem of presentation, language or standard library, but an algorithm. If you have a code generator, then ... why don't you change the generated code to a better (= shortest with the required precision) representation? This is what you do when you write code manually.

put_constant(double value) , :

  • ? std::fixed set_precision, .
  • , double, , () .
  • . N (. ), , .

() , , . , , . , , :

#define USE_L2D __int64 ___tmp = 0;
#define L2D(x) (double&)(___tmp=x)

int main(int argc, char* argv[])
{
    // 2.2 = in memory it is 0x400199999999999A

    USE_L2D
    double f1 = L2D(0x400199999999999A);
    double f2 = 123456.1234567891234567;

    return 0;
}
+3

( % a printf() C); ( C11, 7.21.6.1p8, a,A).

cfile << std::hexfloat << v;

/ hexfloat, C99 %a printf ( , ++ 11 22.4.2.2.2):

printf("%a", v);

, C99:

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

++ 11, ++ 11 . ++ 11 C99 .

+9

-, , std::scientific, std::fixed. -, , . . , , , , ( , ), :

cfile.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );

. ( , .)

+1

I'm not sure that you can float without a problem. Floating points are necessarily losses. Although they may be a subset of the values, you cannot include ALL significant numbers - other equipment may have different representations, so you cannot guarantee that there is no loss of information. Even if you can transmit all this, because this value cannot be represented by the receiving equipment.

A simple stream :: operator <will print as many digits as needed, however, so there is no need to complicate matters.

-4
source

All Articles