P i*_*P i 81 c c++ operator-overloading modulo c++11
我厌恶的C语言(作为一名数学家)就是这样的
(-1) % 8 // comes out as -1, and not 7
fmodf(-1,8) // fails similarly
Run Code Online (Sandbox Code Playgroud)
什么是最好的解决方案?
C++允许模板和运算符重载的可能性,但这些对我来说都是模糊的.感激地收到了例子.
Arm*_*yan 72
首先,我想指出你甚至不能依赖这个事实(-1) % 8 == -1.你唯一可以依靠的就是那个(x / y) * y + ( x % y) == x.但是,余数是否为负是实现定义的.
为什么在这里使用模板?对于整数和多头的过载都可以.
int mod (int a, int b)
{
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}
Run Code Online (Sandbox Code Playgroud)
现在你可以像mod(-1,8)一样调用它,它看起来像是7.
编辑:我在代码中发现了一个错误.如果b为负,它将不起作用.所以我认为这更好:
int mod (int a, int b)
{
if(b < 0) //you can check for b == 0 separately and do what you want
return -mod(-a, -b);
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}
Run Code Online (Sandbox Code Playgroud)
参考:C++ 03第5.6段第4节:
二元/运算符产生商,二元%运算符从第一个表达式除以第二个表达式得到余数.如果/或%的第二个操作数为零,则行为未定义; 否则(a/b)*b + a%b等于a.如果两个操作数都是非负的,那么余数是非负的; 如果没有,余数的符号是实现定义的.
P i*_*P i 12
这是一个C函数,它处理两个操作数的正或负整数OR小数值
#include <math.h>
float mod(float a, float N) {return a - N*floor(a/N);} //return in range [0, N)
Run Code Online (Sandbox Code Playgroud)
从数学的角度来看,这无疑是最优雅的解决方案.但是,我不确定它在处理整数方面是否稳健.转换int - > fp - > int时,有时会出现浮点错误.
我将此代码用于非int,以及int的单独函数.
注意:需要陷阱N = 0!
测试器代码:
#include <math.h>
#include <stdio.h>
float mod(float a, float N)
{
float ret = a - N * floor (a / N);
printf("%f.1 mod %f.1 = %f.1 \n", a, N, ret);
return ret;
}
int main (char* argc, char** argv)
{
printf ("fmodf(-10.2, 2.0) = %f.1 == FAIL! \n\n", fmodf(-10.2, 2.0));
float x;
x = mod(10.2f, 2.0f);
x = mod(10.2f, -2.0f);
x = mod(-10.2f, 2.0f);
x = mod(-10.2f, -2.0f);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(注意:您可以直接从CodePad编译并运行它:http://codepad.org/UOgEqAMA )
输出:
fmodf(-10.2,2.0)= -0.20 ==失败!
10.2 mod 2.0 = 0.2
10.2 mod -2.0 = -1.8
-10.2 mod 2.0 = 1.8
-10.2 mod -2.0 = -0.2
找到正模数的最简单的通用函数是这个 - 它适用于 x 的正值和负值。
int modulo(int x,int N){
return (x % N + N) %N;
}
Run Code Online (Sandbox Code Playgroud)
我刚刚注意到Bjarne Stroustrup标记%为余数运算符,而不是模运算符.
我敢打赌,这是ANSI C&C++规范中的正式名称,滥用术语已经悄悄进入.有没有人知道这个事实?
但如果是这种情况,则C的fmodf()函数(可能还有其他函数)非常具有误导性.它们应该被标记为fremf()等
对于整数,这很简单.做就是了
(((x < 0) ? ((x % N) + N) : x) % N)
Run Code Online (Sandbox Code Playgroud)
我认为这N是积极的,可以代表的类型x.您最喜欢的编译器应该能够优化它,这样它最终只能在汇编程序中进行一次mod操作.
| 归档时间: |
|
| 查看次数: |
232981 次 |
| 最近记录: |