简体   繁体   中英

How do I set the precision of a float variable in c++

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. (eg 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;
}

How do I make "b" equal to the value of "a" rounded to the hundredths place. (eg 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.

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, it did not, while:

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

did; but I would not rely on that. In the first instance the converted c is implicitly converted to double, and in that 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 ).

Banking software should never store money using floating point.

I will not go into details here, but you can read more than you would think there is to know in:

Use fixed-point arithmetic

The idea is as simple as it gets: instead of using floating-point, use integers and simply multiply by some fixed value.

For banking, compute at 100 ths of a cent, or 10,000 ths of a dollar. Thus:

long one_dollar = 10000;  // == 100 cents == 10000 100ths of a cent

To display that dollar, you can simply divide using floating-point arithmetic:

std::cout << std::fixed << std::setprecision(2) << (one_dollar / 10000.0);

If you need to be specific (for example, not letting 0.006 round up to display as 0.01 to your clients, making them believe they have a whole cent when they do not), make sure to get rid of the sub-cent values first:

std::cout << std::fixed << std::setprecision(2) << ((one_dollar / 100) / 100.0);

All other useful operations (addition, subtraction, multiplication, division) work the same as ever.

For your needs

There is no requirement that fixed-point values be stored in multiples of 10000, or even 100. Any multiplier will do. You want to store as pennies? Do that. Easy, peasy, done.

Since you are using C++, you can even write yourself a simple class to make a fixed-point number act like any other numeric type, but that is probably much more than you need for the purposes of your assignment.

If I were you, I'd just use an integer, and create a couple of functions to convert between cents and dollars.

double to_dollars( long cents );
long from_dollars( double dollars );

Thereafter treat every monetary amount as the number of cents you have.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM