【C/C++】四舍五入、向上取整、向下取整、精确取整

IEEE 754 - 维基百科,自由的百科全书 (wikipedia.org)

数值修约 - 维基百科,自由的百科全书 (wikipedia.org)

IEEE-754 在线浮点数转换

IEEE 754标准规定了浮点数的舍入方式:

  1. 就近舍入

    • 即十进制下的四舍五入方式。
    • 对于二进制表示的浮点数,小数位会根据以下规则进行处理:
      • 如果小数数字是1001,大于0.5,则最低位进1。
      • 如果小数数字是0111,小于0.5,则直接舍掉小数数字。
      • 如果小数数字是1000,正好等于0.5的特殊情况;此时,最低位为0则舍掉多余位,最低位为1则进位1。
  2. 朝0舍入

    • 即朝数轴零点方向舍入,直接截尾即可。
  3. 朝正无穷舍入

    • 对正数而言,小数位全为0则直接截尾,不全为0则向最低有效位进1。
    • 对负数而言,不管小数位是多少,直接截尾即可。
  4. 朝负无穷舍入

    • 对负数而言,小数位全为0则直接截尾,不全为0则向最低有效位进1。
    • 对正数而言,不管小数位是多少,直接截尾即可。

格式符 %f,%.nf 默认是四舍五入

#include<stdio.h>

#define BUF_SIZE    (100)

int main()
{
    char buf[BUF_SIZE];
    printf("%f, %.6f, %f, %.6f\n", 1.23456789, 1.23456789, 1.23456712, 1.23456712);
    snprintf(buf, BUF_SIZE, "%f, %.6f, %f, %.6f", 1.23456789, 1.23456789, 1.23456712, 1.23456712);
    printf("%s\n", buf);
    return 0;
}

// 结果
1.234568, 1.234568, 1.234567, 1.234567
1.234568, 1.234568, 1.234567, 1.234567

 

C代码实现

#include <stdio.h>
 
double _pow(double base, int exponent)
{
    double result = 1.0;
 
    if (exponent >= 0) {
        for (int i = 0; i < exponent; i++) {
            result *= base;
        }
    } else {
        for (int i = 0; i < -exponent; i++) {
            result /= base;
        }
    }
 
    return result;
}
 
/**
 * @brief 向下取整(变异朝负无穷舍入)
 *
 * @param bit 精确到第几位,>0 操作小数位,≤0 操作整数位
 * @note 检查精确位后的第一个位数
 */
double _floor_bit(double num, int bit)
{
    double times = _pow(10, bit);
    int int_part = (int)(num * times);
    // 检查要求精确位数的后一位是否为0,不为0负数要减一
    if (num < 0 && (int)(num*times*10)/10.0 != int_part) {
        return (double)(int_part - 1) / times;
    } else {
        return (double)int_part / times;
    }
}
 
/**
 * @brief 向上取整(变异朝正无穷舍入)
 *
 * @param bit 精确到第几位
 */
double _ceil_bit(double num, int bit)
{
    double times = _pow(10, bit);
    int int_part = (int)(num * times);
    // 检查要求精确位数的后一位是否为0,不为0正数要加一
    if (num > 0 && (int)(num*times*10)/10.0 != int_part) {
        return (double)(int_part + 1) / times;
    } else {
        return (double)int_part / times;
    }
}
 
/**
 * @brief 四舍五入(就近舍入)
 *
 * @param bit 精确到第几位
 */
double _round_bit(double num, int bit)
{
    return num < 0 ? _ceil_bit(num - 0.5/_pow(10, bit), bit) : _floor_bit(num + 0.5/_pow(10, bit), bit);
}

/**
 * @brief 精确到位(朝0舍入)
 *
 * @param bit 精确到第几位
 * @note 截断精确位后的数字
 */
double _truncate_bit(double num, int bit)
{
    return num < 0 ? _ceil_bit(num, bit) : _floor_bit(num, bit);
}
 
void test_bit(double num, int bit)
{
    printf("** %s(%f, %d)\n", __func__, num, bit);
    double result_floor = _floor_bit(num, bit);
    printf("向下取整的结果为: %lf\n", result_floor);
 
    double result_ceil = _ceil_bit(num, bit);
    printf("向上取整的结果为: %lf\n", result_ceil);
 
    double result_round = _round_bit(num, bit);
    printf("四舍五入的结果为: %lf\n", result_round);

    double result_truncate = _truncate_bit(num, bit);
    printf("精确到位的结果为: %lf\n\n", result_truncate);
}
 
/**
 * @brief 向下取整(朝负无穷舍入)
 *
 * @param bit 精确到第几位
 * @note 检查精确位后的所有位数
 */
double _floor(double num, int bit)
{
    double times = _pow(10, bit);
    int int_part = (int)(num * times);
    if (num < 0 && num * times != int_part) {
        return (int_part - 1) / times;
    } else {
        return int_part / times;
    }
}
 
/**
 * @brief 向上取整(朝正无穷舍入)
 *
 * @param bit 精确到第几位
 * @note 检查精确位后的所有位数
 */
double _ceil(double num, int bit)
{
    double times = _pow(10, bit);
    int int_part = (int)(num * times);
    if (num > 0 && num * times != int_part) {
        return (int_part + 1) / times;
    } else {
        return int_part / times;
    }
}
 
/**
 * @brief 四舍五入(就近舍入)
 *
 * @param bit 精确到第几位
 */
double _round(double num, int bit)
{
    return num < 0 ? _ceil(num - 0.5/_pow(10, bit), bit) : _floor(num + 0.5/_pow(10, bit), bit);
}

/**
 * @brief 精确到位(朝0舍入)
 *
 * @param bit 精确到第几位
 * @note 截断精确位后的数字
 */
double _truncate(double num, int bit)
{
    return num < 0 ? _ceil(num, bit) : _floor(num, bit);
}
 
void test(double num, int bit)
{
    printf("** %s(%f, %d)\n", __func__, num, bit);
    double result_floor = _floor(num, bit);
    printf("向下取整的结果为: %lf\n", result_floor);
 
    double result_ceil = _ceil(num, bit);
    printf("向上取整的结果为: %lf\n", result_ceil);
 
    double result_round = _round(num, bit);
    printf("四舍五入的结果为: %lf\n", result_round);

    double result_truncate = _truncate(num, bit);
    printf("精确到位的结果为: %lf\n\n", result_truncate);
}
 
 
int main(void)
{
    int bit = 0;
    double num = 12300.000001;
    test(num, bit);
    test_bit(num, bit);
    
    num = -12300.000001;
    test(num, bit);
    test_bit(num, bit);
    
    num = 6.0;
    test_bit(num, bit);
    
    num = -6.0;
    test_bit(num, bit);
    
    num = 6.111;
    test_bit(num, bit);
    
    num = -6.111;
    test_bit(num, bit);
    
    num = 6.888;
    test_bit(num, bit);
    
    num = -6.888;
    test_bit(num, bit);
    
    num = 6.555;
    test_bit(num, bit);
    
    num = -6.555;
    test_bit(num, bit);
    
    num = 6.405;
    test_bit(num, bit);
    
    num = -6.405;
    test_bit(num, bit);
 
    num = 6.415;
    test_bit(num, bit);
    
    num = -6.415;
    test_bit(num, bit);
    
    num = 6.455;
    test_bit(num, bit);
    
    num = -6.455;
    test_bit(num, bit);
    
    num = 6.465;
    test_bit(num, bit);
    
    num = -6.465;
    test_bit(num, bit);
 
    return 0;
}

执行结果

bit -1 0 2
结果

** test(12300.000001, -1)
向下取整的结果为: 12300.000000
向上取整的结果为: 12310.000000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test_bit(12300.000001, -1)
向下取整的结果为: 12300.000000
向上取整的结果为: 12300.000000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test(-12300.000001, -1)
向下取整的结果为: -12310.000000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(-12300.000001, -1)
向下取整的结果为: -12300.000000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(6.000000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.000000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.111000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.111000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.888000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.888000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.555000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.555000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.405000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.405000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.415000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.415000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.455000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.455000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test_bit(6.465000, -1)
向下取整的结果为: 0.000000
向上取整的结果为: 10.000000
四舍五入的结果为: 10.000000
精确到位的结果为: 0.000000

** test_bit(-6.465000, -1)
向下取整的结果为: -10.000000
向上取整的结果为: 0.000000
四舍五入的结果为: -10.000000
精确到位的结果为: 0.000000

** test(12300.000001, 0)
向下取整的结果为: 12300.000000
向上取整的结果为: 12301.000000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test_bit(12300.000001, 0)
向下取整的结果为: 12300.000000
向上取整的结果为: 12300.000000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test(-12300.000001, 0)
向下取整的结果为: -12301.000000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(-12300.000001, 0)
向下取整的结果为: -12300.000000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(6.000000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 6.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.000000, 0)
向下取整的结果为: -6.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.111000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.111000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.888000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 7.000000
精确到位的结果为: 6.000000

** test_bit(-6.888000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -7.000000
精确到位的结果为: -6.000000

** test_bit(6.555000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 7.000000
精确到位的结果为: 6.000000

** test_bit(-6.555000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -7.000000
精确到位的结果为: -6.000000

** test_bit(6.405000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.405000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.415000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.415000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.455000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.455000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.465000, 0)
向下取整的结果为: 6.000000
向上取整的结果为: 7.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.465000, 0)
向下取整的结果为: -7.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test(12300.000001, 2)
向下取整的结果为: 12300.000000
向上取整的结果为: 12300.010000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test_bit(12300.000001, 2)
向下取整的结果为: 12300.000000
向上取整的结果为: 12300.000000
四舍五入的结果为: 12300.000000
精确到位的结果为: 12300.000000

** test(-12300.000001, 2)
向下取整的结果为: -12300.010000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(-12300.000001, 2)
向下取整的结果为: -12300.000000
向上取整的结果为: -12300.000000
四舍五入的结果为: -12300.000000
精确到位的结果为: -12300.000000

** test_bit(6.000000, 2)
向下取整的结果为: 6.000000
向上取整的结果为: 6.000000
四舍五入的结果为: 6.000000
精确到位的结果为: 6.000000

** test_bit(-6.000000, 2)
向下取整的结果为: -6.000000
向上取整的结果为: -6.000000
四舍五入的结果为: -6.000000
精确到位的结果为: -6.000000

** test_bit(6.111000, 2)
向下取整的结果为: 6.110000
向上取整的结果为: 6.120000
四舍五入的结果为: 6.110000
精确到位的结果为: 6.110000

** test_bit(-6.111000, 2)
向下取整的结果为: -6.120000
向上取整的结果为: -6.110000
四舍五入的结果为: -6.110000
精确到位的结果为: -6.110000

** test_bit(6.888000, 2)
向下取整的结果为: 6.880000
向上取整的结果为: 6.890000
四舍五入的结果为: 6.890000
精确到位的结果为: 6.880000

** test_bit(-6.888000, 2)
向下取整的结果为: -6.890000
向上取整的结果为: -6.880000
四舍五入的结果为: -6.890000
精确到位的结果为: -6.880000

** test_bit(6.555000, 2)
向下取整的结果为: 6.550000
向上取整的结果为: 6.560000
四舍五入的结果为: 6.560000
精确到位的结果为: 6.550000

** test_bit(-6.555000, 2)
向下取整的结果为: -6.560000
向上取整的结果为: -6.550000
四舍五入的结果为: -6.560000
精确到位的结果为: -6.550000

** test_bit(6.405000, 2)
向下取整的结果为: 6.400000
向上取整的结果为: 6.410000
四舍五入的结果为: 6.410000
精确到位的结果为: 6.400000

** test_bit(-6.405000, 2)
向下取整的结果为: -6.410000
向上取整的结果为: -6.400000
四舍五入的结果为: -6.410000
精确到位的结果为: -6.400000

** test_bit(6.415000, 2)
向下取整的结果为: 6.410000
向上取整的结果为: 6.420000
四舍五入的结果为: 6.420000
精确到位的结果为: 6.410000

** test_bit(-6.415000, 2)
向下取整的结果为: -6.420000
向上取整的结果为: -6.410000
四舍五入的结果为: -6.420000
精确到位的结果为: -6.410000

** test_bit(6.455000, 2)
向下取整的结果为: 6.450000
向上取整的结果为: 6.460000
四舍五入的结果为: 6.460000
精确到位的结果为: 6.450000

** test_bit(-6.455000, 2)
向下取整的结果为: -6.460000
向上取整的结果为: -6.450000
四舍五入的结果为: -6.460000
精确到位的结果为: -6.450000

** test_bit(6.465000, 2)
向下取整的结果为: 6.460000
向上取整的结果为: 6.470000
四舍五入的结果为: 6.470000
精确到位的结果为: 6.460000

** test_bit(-6.465000, 2)
向下取整的结果为: -6.470000
向上取整的结果为: -6.460000
四舍五入的结果为: -6.470000
精确到位的结果为: -6.460000

posted @ 2024-03-08 20:37  壹点灵异  阅读(1360)  评论(0编辑  收藏  举报