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:
enum
{
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;
dedit.Pattern("%4n");
(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.
|