3

I am using .str(n, std::ios_base::scientific) to print ccp_dec_floats.

I've noticed that it rounds up.

I am using cpp_dec_float for accounting, so I need to round downward. How can this be done?

2 Answers2

3

It doesn't round up. In fact, it does banker's round: See it Live On Coliru

#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>

namespace mp = boost::multiprecision;

int main()
{
    using Dec = mp::cpp_dec_float_50;

    for (Dec d : { 
            Dec( "3.34"),   Dec( "3.35"),   Dec( "3.38"),
            Dec( "2.24"),   Dec( "2.25"),   Dec( "2.28"),
            Dec("-2.24"),   Dec("-2.25"),   Dec("-2.28"),
            Dec("-3.34"),   Dec("-3.35"),   Dec("-3.38"),
            })
    {
        std::cout     << d.str(2, std::ios_base::fixed) 
            << " -> " << d.str(1, std::ios_base::fixed) << "\n";
    }
}

Prints:

3.34 -> 3.3
3.35 -> 3.4
3.38 -> 3.4
2.24 -> 2.2
2.25 -> 2.2
2.28 -> 2.3
-2.24 -> -2.2
-2.25 -> -2.2
-2.28 -> -2.3
-3.34 -> -3.3
-3.35 -> -3.4
-3.38 -> -3.4

So if you want another kind of rounding, you'd want to write it explicitly

Here's a generic approach (Live On Coliru)

template <int decimals = 0, typename T>
T round_towards_zero(T const& v)
{
    static const T scale = pow(T(10), decimals);

    if (v.is_zero())
        return v;

    // ceil/floor is found via ADL and uses expression templates for optimization
    if (v<0)
        return ceil(v*scale)/scale;
    else
        // floor is found via ADL and uses expression templates for optimization
        return floor(v*scale)/scale;
}

which hopefully compiles down to optimal code due to statically known scale factor and the use of expression templates in Boost Multiprecision library.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 2
    Here's a proof of concept implementation of `round_towards_zero` http://coliru.stacked-crooked.com/a/726e31b3565d73c6 – sehe Apr 12 '14 at 19:42
1

I assume you're trying to achieve rounding to a certain decimal point, correct?

Standard rounding

double rounding_func(double in, double precision){
   return round(in*pow(10,precision))/pow(10,precision);              
}

But as your title says, you're trying to force it to round down, so consider

double rounding_func(double in, double precision){
   return floor(in*pow(10,precision))/pow(10,precision);              
}

Good luck!

Outsider
  • 550
  • 3
  • 9
  • Yeah, you can definitely use doubles like that. All that is happening is we're multiplying the number by 10 to the number of decimal places we want to keep, round the remaining decimal places, then divide again by that power of 10. – Outsider Apr 12 '14 at 16:56
  • I've never used the boost library to be honest, but I can't see why it wouldn't work. I assume cpp_dec_float is just a floating point number formatted for Boost. You might need to use boost specific functions to do the actual rounding, but the concept should work. – Outsider Apr 12 '14 at 17:19
  • 1
    I've just added this to my answer. – sehe Apr 12 '14 at 19:44