Home > Software design >  How do I set the precision of a float variable in c
How do I set the precision of a float variable in c

Time:12-04

It will print 88.89 to the console because, 88.888 with a hundredths place rounding precision equals 88.89.

How do I make "b" equal to the value of "a" rounded to the hundredths place. (e.g. 88.89)

How do I make it so its like, | float b = "a" rounded to nearest hundredths place etc.

Basically how do I make a float equal to another float, but with lower precision

EXAMPLE:

a = 88.888
b = 88.89
c = 88.9

I don't want it to print to console, I just want these rounded values given to a variable because I require a rounded number in my program, and all the other numbers are 2 decimal places out. It would throw off the program if it was more than the hundredths place (banking software, we don't have a denomination past cents. We just need hundredths place basically).

#include<iostream>
#include<iomanip>
using namespace std;
        
int main(){
        
    float a = 88.888;
        
    cout << fixed << setprecision(2) << a << endl; 
    
    float b;
        
    return 0;
}

CodePudding user response:

How do I make "b" equal to the value of "a" rounded to the hundredths place. (e.g. 88.89)

Depending on the particular target value, you cannot. For example, the number 88.89 is not representable in 32 bit IEEE-754 floating point format, so you simply cannot have a float with that value in that representation.

What you can have instead is a value that is very very close to it, such as 88.8899993896484375. If this is what you want, then it is achievable.

A simple solution is to use the string formatting facilities. The character streams have manipulator called std::setprecision, as you have shown. Simply convert the float to a string with desired precision, and then convert the string back to float.

Another solution is to use a bit of math. An intuitive and seemingly trivial solution would be:

std::round(a * 100.f) / 100.f;

There is a problem however. When the input value is near the threshold where direction of rounding changes, the lack of floating point precision can cause the input value to be on the wrong side for the purpose of the rounding direction.

For example, the closest representable value to 0.005 is actually 0.004999999888241291046142578125 which rounds down instead of up that we would have hoped from 0.005.

We can work around this by using one more decimal of precision and do an intermediate rounding:

std::round(
    std::round(a * 1000.f) / 10.f
) / 100.f;

banking software, we don't have a denomination past cents

I recommend to not use finite precision floating point for banking software. Use integers to represent cents when you don't want more precision. And when you do need more precision, use arbitrary precision arithmetic.

CodePudding user response:

It is perhaps not entirely clear what you require, but I assume:

float precision( float f, int places )
{
    float n = std::pow(10.0f, places ) ;
    return std::round(f * n) / n ;
}

Then given:

float a = 8.888 ;

The following:

float b = precision( a, 2 ) ;  // 8.89
float c = precision( a, 1 ) ;  // 8.9

However be clear that while the mathematical value of b for example is 8.89 and default standard output methods will print it as such, the stored value will be as near to 8.89 as the binary floating point representation allows. So for example while:

std::cout << a << '\n' ;
std::cout << b << '\n' ;
std::cout << c << '\n' ;

Outputs:

8.888
8.89
8.9

Setting the output precision reveals the limitation of representing decimal real values in binary floating point:

std::cout << std::setprecision(8) ;
std::cout << a << '\n' ;
std::cout << b << '\n' ;
std::cout << c << '\n' ;

outputs:

8.8879995
8.8900003
8.8999996

Which is fine and probably meets your requirements, but you may need to be aware to avoid errors. For example do not expect c == 8.9 to be true - Expect:

std::cout << ((c == 8.9) ? "equal\n" : "not equal\n") ;

to output not equal. In my test:

std::cout << ((c == 8.9f) ? "equal\n" : "not equal\n") ;

did outout equal; but I would not rely on that. In the first instance the converted c is implicitly converted to double, and in that conversion its value differs form the literal double 8.9.

That of course is a general rule not to compare a floating point value for exact equality. Instead you should:

std::cout << ((c - 8.9f < 0.01f) ? "equal\n" : "not equal\n") ;

For this reason, you would not generally use binary floating point for banking software. You would use decimal floating point. For that you would need library support or a different language. C# (and any .Net supported language) for example has a decimal type with at least 28 digits of precision.

Financial apps in general should not in any event round to the nearest cent in many cases - share prices and currency exchange rates for example are expressed in fractions of a cent. You would only want to round at the final result.

Suffice it to say that there are issues to resolve beside the simple rounding of the stored value (as opposed to rounding the presentation).

  • Related