0

I'm looking for a way to force the computer to calculate a floating-point operation with a set number of significant digits. This is for pure learning reasons, so I don't care about the loss of accuracy in the result.

For example, if I have:

float a = 1.67;
float b = 10.0;
float c = 0.01

float d = a * b + c;

And I want every number represented with 3 significant digits, I'd like to see:

d = 16.7;

Not:

d = 16.71;

So far, I got this as a possible answer: Limit floating point precision?

But it would bloat my code to turn every floating-point variable into one with the precision I want using that strategy. And then doing to the same with the result.

Is there an automatic way to fix the precision?

Community
  • 1
  • 1
Heathcliff
  • 3,048
  • 4
  • 25
  • 44
  • 3
    Would changing the precision of printed output be enough or does it have to be the precision of the value in memory? The thing to really consider is the inaccuracy of float types to begin with (such as not being able to even represent 0.01): http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems – TheZ Oct 08 '12 at 22:44
  • No, I would need the precision to be taken into account in memory. For example: following the case in the original post, if I were to add 0.04 to the float variable d and then print it with precision 3 (like cout.setprecision(3); cout << d), if d had been saved as 16.7, the mid storage would save 16.74, and print "16.7"; but if it had been saved as 16.71, the mid storage would save 16.75 and print "16.8" as a result. I know about the inaccuracy of float types, I would be working with a worse precision to begin with. – Heathcliff Oct 08 '12 at 23:44
  • Why, exactly, do you think you need this? If you are working with money, then yes there are some real issues here, real enough that you might not want to be using the reals (float or double) at all. You probably want a fixed point package instead. If you're doing scientific calculations with limited precision on the data, those intermediate results are best kept at greater precision than that of the data. You do not want to round those intermediate results. – David Hammen Oct 09 '12 at 00:15
  • Homework. I'm told I have to do it this way. – Heathcliff Oct 09 '12 at 12:23

2 Answers2

1

The floating point data types are binary floating points, i.e., they have precision in terms of binary digits and it is actually impossible to represent the decimal values exactly in general. As a result, you will have some problems truncating the operations to the correct number of decimal places in the first place. What could work is to format a floating point value after each operation with a precision of n digits (e.g. with n == 3) and convert this back into a floating value. This won't be particularly efficient but would work. To avoid littering the code with the corresponding truncation logic, you would encapsulate the operations you need into a class which does the operation an appropriately truncates the result.

Alternatively, you could implement the necessary logic using a significand and a suitable base 10 exponent. The significant would be restricted to values between -999 and 999. It is probably more work to implement a class like this but the result is likely to be more efficient.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

So far, I got this as a possible answer: Limit floating point precision?

Read the second answer, which received ten votes, rather than the accepted one, which only received four votes. Don't do it.

You don't want to do this when you do calculations on paper, let alone on a computer. Those intermediate calculations are best done to at least one extra significant digit, and preferably two or more, than the underlying data indicate. You truncate to the precision indicated by the data at the very end. The only reason we do this on paper is because people aren't that good at dealing with a lot of digits. It's a short circuit operation that is tuned to how people calculate (or miscalculate).

All that you are doing by rounding intermediate calculations accomplishes is to create an opening for errors to creep in and slowing the computer down, oftentimes by a quite a bit. Don't worry about the extra precision in those intermediate results. Simply use display the results to the desired precision on output.

The opposite problem sometimes does apply. You may need to worry about loss of precision in your intermediate results. Sometimes that loss of precision will mean changing from floats to doubles, or from doubles to variable precision arithmetic (which is slow).

Community
  • 1
  • 1
David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • I had read that answer. I had the suspiction that it might slow down the program, but that isn't important. What I need to do is do the calculations with a certain number of significant digits, given in the problem. So, for instance, I may have a problem that tells me that I have to calculate a certain thing in which the mantisse has 4 digits. That's why I need to set the precision that way. – Heathcliff Oct 08 '12 at 23:55
  • But you don't need to set the precision that way. What you need is to have the final result displayed that way. Both C-style output (the `printf` family of functions) and C++ style output (output streams such as `std::cout`) provide mechanisms to control the precision. – David Hammen Oct 09 '12 at 00:06