【C/C++】四舍五入、向上取整、向下取整、精确取整
IEEE 754 - 维基百科,自由的百科全书 (wikipedia.org)
数值修约 - 维基百科,自由的百科全书 (wikipedia.org)
IEEE 754标准规定了浮点数的舍入方式:
-
就近舍入:
- 即十进制下的四舍五入方式。
- 对于二进制表示的浮点数,小数位会根据以下规则进行处理:
- 如果小数数字是1001,大于0.5,则最低位进1。
- 如果小数数字是0111,小于0.5,则直接舍掉小数数字。
- 如果小数数字是1000,正好等于0.5的特殊情况;此时,最低位为0则舍掉多余位,最低位为1则进位1。
-
朝0舍入:
- 即朝数轴零点方向舍入,直接截尾即可。
-
朝正无穷舍入:
- 对正数而言,小数位全为0则直接截尾,不全为0则向最低有效位进1。
- 对负数而言,不管小数位是多少,直接截尾即可。
-
朝负无穷舍入:
- 对负数而言,小数位全为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) ** test_bit(12300.000001, -1) ** test(-12300.000001, -1) ** test_bit(-12300.000001, -1) ** test_bit(6.000000, -1) ** test_bit(-6.000000, -1) ** test_bit(6.111000, -1) ** test_bit(-6.111000, -1) ** test_bit(6.888000, -1) ** test_bit(-6.888000, -1) ** test_bit(6.555000, -1) ** test_bit(-6.555000, -1) ** test_bit(6.405000, -1) ** test_bit(-6.405000, -1) ** test_bit(6.415000, -1) ** test_bit(-6.415000, -1) ** test_bit(6.455000, -1) ** test_bit(-6.455000, -1) ** test_bit(6.465000, -1) ** test_bit(-6.465000, -1) |
** test(12300.000001, 0) ** test_bit(12300.000001, 0) ** test(-12300.000001, 0) ** test_bit(-12300.000001, 0) ** test_bit(6.000000, 0) ** test_bit(-6.000000, 0) ** test_bit(6.111000, 0) ** test_bit(-6.111000, 0) ** test_bit(6.888000, 0) ** test_bit(-6.888000, 0) ** test_bit(6.555000, 0) ** test_bit(-6.555000, 0) ** test_bit(6.405000, 0) ** test_bit(-6.405000, 0) ** test_bit(6.415000, 0) ** test_bit(-6.415000, 0) ** test_bit(6.455000, 0) ** test_bit(-6.455000, 0) ** test_bit(6.465000, 0) ** test_bit(-6.465000, 0) |
** test(12300.000001, 2) ** test_bit(12300.000001, 2) ** test(-12300.000001, 2) ** test_bit(-12300.000001, 2) ** test_bit(6.000000, 2) ** test_bit(-6.000000, 2) ** test_bit(6.111000, 2) ** test_bit(-6.111000, 2) ** test_bit(6.888000, 2) ** test_bit(-6.888000, 2) ** test_bit(6.555000, 2) ** test_bit(-6.555000, 2) ** test_bit(6.405000, 2) ** test_bit(-6.405000, 2) ** test_bit(6.415000, 2) ** test_bit(-6.415000, 2) ** test_bit(6.455000, 2) ** test_bit(-6.455000, 2) ** test_bit(6.465000, 2) ** test_bit(-6.465000, 2) |