安全地四舍五入到下一个较小的倍数
Safely round to next smaller multiple
考虑:
int a, b;
int c = b * (a / b)
我认为应该很清楚它对正数的作用:c被设置为b的倍数,后者相对于a较小。
示例:设b = 2
,则:
a = 0 => c = 0
a = 1 => c = 0
a = 2 => c = 2
a = 3 => c = 2
然而,对于负数,它的工作方式正好相反:它取b的下一个较大(较负)倍数。同时取b的第二个较小(较负的)倍数的最佳方法是什么
怎么样:
#include <cstdlib>
#include <iostream>
int round_down(int val, int unit) {
std::div_t div_result = std::div(val, unit);
int candidate = div_result.quot * unit;
return candidate <= val ? candidate :
unit >= 0 ? candidate - unit :
candidate + unit;
}
int main() {
std::cout << round_down(9, 7) << std::endl;
std::cout << round_down(13, 2) << std::endl;
std::cout << round_down(15, 3) << std::endl;
std::cout << round_down(-9, 7) << std::endl;
std::cout << round_down(-13, 2) << std::endl;
std::cout << round_down(-15, 3) << std::endl;
std::cout << round_down(9, -7) << std::endl;
std::cout << round_down(13, -2) << std::endl;
std::cout << round_down(15, -3) << std::endl;
std::cout << round_down(-9, -7) << std::endl;
std::cout << round_down(-13, -2) << std::endl;
std::cout << round_down(-15, -3) << std::endl;
}
注意,在C++11之前,内置除法运算符/
的舍入方向是实现定义的。因此,我使用std::div()
。引用自cppreference(强调矿):
二进制运算符将第一个操作数除以第二个操作数(之后通常的算术转换)
对于整数操作数,它产生代数商
商按实现定义的方向四舍五入。(直到C++11)
商为向零截断(丢弃小数部分)。(从C++11开始)
…
注意:在C++11之前,如果一个或两个操作数都为二进制运算符%为负,剩余部分的符号为实现定义,因为它取决于整数除法的舍入方向函数std::div在这种情况下提供了定义良好的行为
如果a<0
,您只需要从a
中减去b+1
,然后将其传递给您的函数:
#include <iostream>
using namespace std;
int main()
{
cout << "---------------------------------" << endl;
for (int bi = 1; bi < 10; bi++)
{
for (int ai = -10; ai < 10; ai++)
{
int a = ai;
int b = bi;
if (a < 0)
a -= b + 1;
int c = b * (std::div(a / b));
cout << "a = " << a << ",b = " << b << " => c = " << c << endl;
}
cout << "---------------------------------" << endl;
}
}
输出:
---------------------------------
a = -12,b = 1 => c = -12
a = -11,b = 1 => c = -11
a = -10,b = 1 => c = -10
a = -9,b = 1 => c = -9
a = -8,b = 1 => c = -8
a = -7,b = 1 => c = -7
a = -6,b = 1 => c = -6
a = -5,b = 1 => c = -5
a = -4,b = 1 => c = -4
a = -3,b = 1 => c = -3
a = 0,b = 1 => c = 0
a = 1,b = 1 => c = 1
a = 2,b = 1 => c = 2
a = 3,b = 1 => c = 3
a = 4,b = 1 => c = 4
a = 5,b = 1 => c = 5
a = 6,b = 1 => c = 6
a = 7,b = 1 => c = 7
a = 8,b = 1 => c = 8
a = 9,b = 1 => c = 9
---------------------------------
a = -13,b = 2 => c = -12
a = -12,b = 2 => c = -12
a = -11,b = 2 => c = -10
a = -10,b = 2 => c = -10
a = -9,b = 2 => c = -8
a = -8,b = 2 => c = -8
a = -7,b = 2 => c = -6
a = -6,b = 2 => c = -6
a = -5,b = 2 => c = -4
a = -4,b = 2 => c = -4
a = 0,b = 2 => c = 0
a = 1,b = 2 => c = 0
a = 2,b = 2 => c = 2
a = 3,b = 2 => c = 2
a = 4,b = 2 => c = 4
a = 5,b = 2 => c = 4
a = 6,b = 2 => c = 6
a = 7,b = 2 => c = 6
a = 8,b = 2 => c = 8
a = 9,b = 2 => c = 8
---------------------------------
a = -14,b = 3 => c = -12
a = -13,b = 3 => c = -12
a = -12,b = 3 => c = -12
a = -11,b = 3 => c = -9
a = -10,b = 3 => c = -9
a = -9,b = 3 => c = -9
a = -8,b = 3 => c = -6
a = -7,b = 3 => c = -6
a = -6,b = 3 => c = -6
a = -5,b = 3 => c = -3
a = 0,b = 3 => c = 0
a = 1,b = 3 => c = 0
a = 2,b = 3 => c = 0
a = 3,b = 3 => c = 3
a = 4,b = 3 => c = 3
a = 5,b = 3 => c = 3
a = 6,b = 3 => c = 6
a = 7,b = 3 => c = 6
a = 8,b = 3 => c = 6
a = 9,b = 3 => c = 9
---------------------------------
a = -15,b = 4 => c = -12
a = -14,b = 4 => c = -12
a = -13,b = 4 => c = -12
a = -12,b = 4 => c = -12
a = -11,b = 4 => c = -8
a = -10,b = 4 => c = -8
a = -9,b = 4 => c = -8
a = -8,b = 4 => c = -8
a = -7,b = 4 => c = -4
a = -6,b = 4 => c = -4
a = 0,b = 4 => c = 0
a = 1,b = 4 => c = 0
a = 2,b = 4 => c = 0
a = 3,b = 4 => c = 0
a = 4,b = 4 => c = 4
a = 5,b = 4 => c = 4
a = 6,b = 4 => c = 4
a = 7,b = 4 => c = 4
a = 8,b = 4 => c = 8
a = 9,b = 4 => c = 8
---------------------------------
a = -16,b = 5 => c = -15
a = -15,b = 5 => c = -15
a = -14,b = 5 => c = -10
a = -13,b = 5 => c = -10
a = -12,b = 5 => c = -10
a = -11,b = 5 => c = -10
a = -10,b = 5 => c = -10
a = -9,b = 5 => c = -5
a = -8,b = 5 => c = -5
a = -7,b = 5 => c = -5
a = 0,b = 5 => c = 0
a = 1,b = 5 => c = 0
a = 2,b = 5 => c = 0
a = 3,b = 5 => c = 0
a = 4,b = 5 => c = 0
a = 5,b = 5 => c = 5
a = 6,b = 5 => c = 5
a = 7,b = 5 => c = 5
a = 8,b = 5 => c = 5
a = 9,b = 5 => c = 5
---------------------------------
a = -17,b = 6 => c = -12
a = -16,b = 6 => c = -12
a = -15,b = 6 => c = -12
a = -14,b = 6 => c = -12
a = -13,b = 6 => c = -12
a = -12,b = 6 => c = -12
a = -11,b = 6 => c = -6
a = -10,b = 6 => c = -6
a = -9,b = 6 => c = -6
a = -8,b = 6 => c = -6
a = 0,b = 6 => c = 0
a = 1,b = 6 => c = 0
a = 2,b = 6 => c = 0
a = 3,b = 6 => c = 0
a = 4,b = 6 => c = 0
a = 5,b = 6 => c = 0
a = 6,b = 6 => c = 6
a = 7,b = 6 => c = 6
a = 8,b = 6 => c = 6
a = 9,b = 6 => c = 6
---------------------------------
a = -18,b = 7 => c = -14
a = -17,b = 7 => c = -14
a = -16,b = 7 => c = -14
a = -15,b = 7 => c = -14
a = -14,b = 7 => c = -14
a = -13,b = 7 => c = -7
a = -12,b = 7 => c = -7
a = -11,b = 7 => c = -7
a = -10,b = 7 => c = -7
a = -9,b = 7 => c = -7
a = 0,b = 7 => c = 0
a = 1,b = 7 => c = 0
a = 2,b = 7 => c = 0
a = 3,b = 7 => c = 0
a = 4,b = 7 => c = 0
a = 5,b = 7 => c = 0
a = 6,b = 7 => c = 0
a = 7,b = 7 => c = 7
a = 8,b = 7 => c = 7
a = 9,b = 7 => c = 7
---------------------------------
a = -19,b = 8 => c = -16
a = -18,b = 8 => c = -16
a = -17,b = 8 => c = -16
a = -16,b = 8 => c = -16
a = -15,b = 8 => c = -8
a = -14,b = 8 => c = -8
a = -13,b = 8 => c = -8
a = -12,b = 8 => c = -8
a = -11,b = 8 => c = -8
a = -10,b = 8 => c = -8
a = 0,b = 8 => c = 0
a = 1,b = 8 => c = 0
a = 2,b = 8 => c = 0
a = 3,b = 8 => c = 0
a = 4,b = 8 => c = 0
a = 5,b = 8 => c = 0
a = 6,b = 8 => c = 0
a = 7,b = 8 => c = 0
a = 8,b = 8 => c = 8
a = 9,b = 8 => c = 8
---------------------------------
a = -20,b = 9 => c = -18
a = -19,b = 9 => c = -18
a = -18,b = 9 => c = -18
a = -17,b = 9 => c = -9
a = -16,b = 9 => c = -9
a = -15,b = 9 => c = -9
a = -14,b = 9 => c = -9
a = -13,b = 9 => c = -9
a = -12,b = 9 => c = -9
a = -11,b = 9 => c = -9
a = 0,b = 9 => c = 0
a = 1,b = 9 => c = 0
a = 2,b = 9 => c = 0
a = 3,b = 9 => c = 0
a = 4,b = 9 => c = 0
a = 5,b = 9 => c = 0
a = 6,b = 9 => c = 0
a = 7,b = 9 => c = 0
a = 8,b = 9 => c = 0
a = 9,b = 9 => c = 9
---------------------------------
您引用的代码的行为实际上是正确的。负整数除法的定义是这样的,对于m和n是正整数,以下是真的:
-(m)/n=-(m/n)
因此,我在这里假设,你实际上在问的是如何获得:
a = -1 => c = -2
a = -2 => c = -2
a = -3 => c = -4
a = -4 => c = -4
a = -5 => c = -6
在这种情况下,不要使用整数除法,这不是您想要的。你想要的是浮点除法的地板。幸运的是,有楼层功能可以帮你做这件事。试试这个:
int c = b * floor((double)a / (double)b);
它应该给你想要的东西。
相关文章:
- 重新定位图像时如何前进到下一个内存块
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 用于在 C++ 中使用 while 循环查找下一个素数的简单函数
- CIN 仅在输入非数字值时跳过下一个 CIN
- 查找最小的下一个更大的元素
- 转到基于范围的 for 循环中的下一个迭代器
- 如何检查流中文件的下一个单词是否为 alpha?
- 如何打印下一个字母直到 Z 并继续到 A?
- 在使用堆栈为下一个最大数字编写代码时面临 SIGSEGV(分段错误)
- 使用一个内存集数组和单个堆栈在 O(n) 中查找数组的下一个更大元素
- 有没有一种标准方法可以在C++中获取第 n 个"下一个"浮点值
- 下一个云桌面客户端构建过程
- C++自定义流操纵器,用于更改流上的下一个字符串
- 链表指针赋值为什么我们不能直接将尾巴分配给 temp 而不是尾巴>尾巴下一个
- 下一个排列定义
- 查找下一个具有真值C++的数组索引
- 如何比较文件中包含的下一个字符
- 将正数四舍五入到下一个最接近的 5 倍数
- 安全地四舍五入到下一个较小的倍数
- 如何将浮点四舍五入到C++中的下一个0.5增量