Status & Roadmap
Authors & License
Funding Ultimate++
Search on this site

SourceForge.net Logo

About rounding double values

Standard C math library defines two rounding functions:


floor - rounds to the nearest non-greater float without decimal digits, i.e.


floor(-2.8) = floor(-2.4) = -3, floor(8) = floor(8.2) = floor(8.8) = 8


ceil - rounds to the nearest non-lower float without decimal digits, i.e.


ceil(-2.8) = ceil(-2.4) = -2, ceil(8.2) = ceil(8.8) = ceil(9) = 9


In addition to these standard functions, U++ defines (in Core/util.h) a few of its own:


int fround(double x);

int ffloor(double x);

int fceil(double x);


These combine rounding (to the nearest integer, to the nearest non-greater, to the nearest non-lower integer, respectively) with truncation of float to integer.


int ilog10(double d);

double ipow10(int i);

double normalize(double d, int& exponent);


These functions can be used to manipulate the order magnitude of floats. ilog10 returns the greatest integer i such that 10^i <= d, ipow10 calculates 10^i (should be relatively fast, at least for reasonable exponents), normalize transforms a float d to the form mantissa * 10^exponent, where mantissa (the returned double) lies in the semi-closed interval [1, 10).


double roundr(double d, int digits);

double floorr(double d, int digits);

double ceilr(double d, int digits);


These functions round given float to the given number of __valid__ digits (i.e. relative to its magnitude).


All in all, the simple rounding you are asking for is currently not present, but it's relatively easy to implement, e.g.:


round(d, n) = floor(d / ipow10(n) + 0.5) * ipow10(n)


But your example (where you are using the rounding function to initialize an edit field), is still something a bit different, what you are demonstrating here is formatting a float to the given number of digits. If you look into Core/Format.h, you'll find the following functions:




    FD_SIGN     = 0x01, // always prepend sign (+10)

    FD_REL      = 0x02, // relative decimal places (valid digits)

    FD_SIGN_EXP = 0x04, // always prepend sign to exponent (1e+2)

    FD_CAP_E    = 0x08, // capital E for exponent (1E10)

    FD_ZERO     = 0x10, // keep trailing zeros (1.25000)

    FD_FIX      = 0x20, // always use fixed notation (FormatDouble)

    FD_EXP      = 0x40, // always use exponential notation (FormatDouble)


String         FormatDoubleDigits(double d, int digits, int flags, int& exponent);

String         FormatDouble(double d, int digits, int flags = 0, int fill_exp = 0);

String         FormatDoubleFix(double d, int digits, int flags = 0);

String         FormatDoubleExp(double d, int digits, int flags = 0, int fill_exp = 0);


You can use these to perform almost any imaginable (reasonable) float formatting. For a start try FormatDouble(x, digits), I suppose this should do something similar to your MyRoundDouble.


There's still another option using EditDouble. It has a method called Pattern, which sets the formatting string for NFormat which is used to generate the textual representation of the number. To round to a fixed number of decimal digits, use e.g.


EditDouble dedit;



(You can also use the more traditional C-style formatters, like %4g or %3f, but the %n formatter is more flexible).


Note that Pattern is actually method of ConvertDouble, which is one of base classes for EditDouble.


Last edit by unodgs on 08/20/2006. Do you want to contribute?. T++