我最讨厌的C派生语言之一(作为一个数学家)是
(-1) % 8 // comes out as -1, and not 7
fmodf(-1,8) // fails similarly最好的解决方案是什么?
C++允许模板和操作符重载的可能性,但这两者对我来说都是浑水摸鱼。感激不尽地收到示例。
发布于 2010-10-23 17:25:07
首先,我想指出的是,你甚至不能依赖(-1) % 8 == -1这个事实。你唯一可以依赖的就是那个(x / y) * y + ( x % y) == x。但是,其余部分是否为负取决于实现定义。
现在为什么要在这里使用模板呢?ints和long类型的重载就可以了。
int mod (int a, int b)
{
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}现在你可以把它叫做mod(-1,8),它看起来是7。
编辑:我在代码中发现了一个bug。如果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;
}引用: C++03第5.6条第4条:
二元/运算符产生商,二元%运算符产生第一个表达式除以第二个表达式的余数。如果/或%的第二个操作数为0,则行为未定义;否则( a /b)*b + a%b等于a。如果两个操作数都为非负,则余数为非负;如果不是,则余数的符号为implementation-defined.
发布于 2010-10-23 17:15:30
下面是一个C函数,它处理两个操作数的正、负整数或小数值
#include <math.h>
float mod(float a, float N) {return a - N*floor(a/N);} //return in range [0, N)从数学的角度来看,这无疑是最优雅的解决方案。但是,我不确定它在处理整数时是否健壮。在转换int -> fp -> int时,有时会出现浮点错误。
我将此代码用于非int s,并将一个单独的函数用于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;
}(注意:您可以直接在CodePad:http://codepad.org/UOgEqAMA中编译并运行它)
输出:
fmodf(- 10.2,2.0) = -0.20 ==故障!10.2模块2.0 = 0.2
10.2模块-2.0 = -1.8
-10.2模块2.0 = 1.8
-10.2模块-2.0 = -0.2
发布于 2010-11-01 11:54:40
我刚刚注意到,Bjarne Stroustrup将%标记为剩余运算符,而不是模运算符。
我敢打赌,这是它在ANSI & C++规范中的正式名称,术语的滥用已经悄然而至。有人知道这是事实吗?
但如果是这种情况,那么C的fmodf()函数(可能还有其他函数)是非常误导的。它们应该被标记为fremf(),等等
https://stackoverflow.com/questions/4003232
复制相似问题