Tiến Trần
Tiến Trần

Reputation: 21

Rounding a float number to a certain precision

I want to round a float to maximum 4 decimals places. It mean 0.333333333 will be 0.3333, but 0.33 is still 0.33

Upvotes: 2

Views: 7696

Answers (5)

Kenny Tutorials
Kenny Tutorials

Reputation: 41

Use _vsnprintf

I think the best solution for this is to just format the string. Because what if we don't need to output this number to the console, but save it in a std::string variable or char[] or something like that. This solution is flexible because it is the same if you output a number to the console and used the std::setprecision() function, but also returning this number to char[].

So for this I used _vsnprintf and va_list. All it does is format the string as needed, in this case float value.

int FormatString(char* buf, size_t buf_size, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    
    int w = _vsnprintf(buf, buf_size, fmt, args);
    va_end(args);
    if (buf == NULL)
        return w;
    if (w == -1 || w >= (int)buf_size)
        w = (int)buf_size - 1;
    buf[w] = 0;
    return w;
}
    
int FormatStringFloat(char* buf, int buf_size, const void* p_data, const char* format) {
    return FormatString(buf, buf_size, format, *(const float*)p_data);
}

Example

#include "iostream"
#include "string"
#define ARRAY_SIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR))))

int main() {

 float value = 3.343535f;
 char buf[64];
 FormatStringFloat(buf, ARRAY_SIZE(buf), (void*)&value, "%.2f");
 std::cout << std::string(buf) << std::endl;
 return 0;
}

So by using "%.2f" we get from the 3.343535 => 3.34.

Upvotes: 0

Marek R
Marek R

Reputation: 37697

Assuming you need print rounded number, this is one of a proper solutions:

cout << setprecision(4) << x << '\n';

std::setprecision documentation.

Live demo

Until more details are not provided it is impossible to provide a better answer.

Please note if you are planing to round number x then print it, it will end with big headache, since some corner cases can produce much longer results then expected.

Upvotes: 0

einpoklum
einpoklum

Reputation: 131547

Cast it into a fixed-point type

If you want to have your results rounded, with a fixed number of decimal digits, you're hinting that you don't really need the "floating" aspect of floating point numbers. Well, in this case, cast your value to a type which represents such numbers. Essentially, that would be a (run-time-variable) integer numerator and a compile-time-fixed denominator (which in your case would be 10,000).

There's an old question here on the site about doing fixed-point math:

What's the best way to do fixed-point math?

but I would suggest you consider the CNL library as something recent/popular. Also, several proposals have been made to add fixed-point types to the standard library. I don't know which one is the farthest advance, but have a look at this one: Fixed-Point Real Numbers by John McFarlane.

Back to your specific case: Fixed-point types can typically be constructed from floating-point ones. Just do that.

Upvotes: 2

einpoklum
einpoklum

Reputation: 131547

Use the std::round() function

The C++ standard library offers functions for performing rounding. For floats, it is:

float round ( float arg );

this will round arg to the nearest integral value. Now, you want a different decimal resolution. So don't round your value, round your value times 10000, so your singles digit is now the former 0.0001 digit. Or more generally:

float my_round(
    float x,
    int num_decimal_precision_digits)  
{
    float power_of_10 = std::pow(10, num_decimal_precision_digits);
    return std::round(x * power_of_10)  / power_of_10;
}

Note that there may be accuracy issues, as floating-point computations and representations are only accurate to within a certain number of digits, and in my_round we have at least four sources of such inaccuracy: The power-of-10 calculation, the multiplication, the devision and the actual rounding.

Upvotes: 4

YaleCheung
YaleCheung

Reputation: 620

Here is a solution, for example:

float ret = float(round(0.333333333 * 10000)) / 10000)

You can write it as a function. Maybe there would be a better way?

Upvotes: 0

Related Questions