SQL Round Function

前端 未结 7 1288
有刺的猬
有刺的猬 2021-01-13 10:00

round(45.923,-1) gives a result of 50. Why is this? How it is calculated?

(sorry guys i was mistaken with earlier version of this question suggestin

7条回答
  •  鱼传尺愫
    2021-01-13 10:36

    As for how, start by considering how you'd round a (positive) float to the nearest integer. Casting a float to an int truncates it. Adding 0.5 to a (positive) float will increment the integer portion precisely when we want to round up (when the decimal portion >= 0.5). This gives the following:

    double round(double x) {
        return (long long)(x + 0.5);
    }
    

    To add support for the precision parameter, note that (for e.g. round(123456.789, -3)) adding 500 and truncating in the thousands place is essentially the same as adding 0.5 and to rounding to the nearest integer, it's just that the decimal point is in a different position. To move the radix point around, we need left and right shift operations, which are equivalent to multiplying by the base raised to the shift amount. That is, 0x1234 >> 3 is the same as 0x1234 / 2**3 and 0x1234 * 2**-3 in base 2. In base 10:

    123456.789 >> 3 == 123456.789 / 10**3 == 123456.789 * 10**-3 == 123.456789
    

    For round(123456.789, -3), this means we can do the above multiplication to move the decimal point, add 0.5, truncate, then perform the opposite multiplication to move the decimal point back.

    double round(double x, double p) {
        return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
    }
    

    Rounding by adding 0.5 and truncating works fine for non-negative numbers, but it rounds the wrong way for negative numbers. There are a few solutions. If you have an efficient sign() function (which returns -1, 0 or 1, depending on whether a number is <0, ==0 or >0, respectively), you can:

    double round(double x, double p) {
        return ((long long)((x * pow10(p))) + sign(x) * 0.5) * pow10(-p);
    }
    

    If not, there's:

    double round(double x, double p) {
        if (x<0) 
          return - round(-x, p);
        return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
    }
    

提交回复
热议问题