首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C/C++/Obj-C中编写处理负数的模(%)运算符

如何在C/C++/Obj-C中编写处理负数的模(%)运算符
EN

Stack Overflow用户
提问于 2010-10-23 17:10:09
回答 13查看 245.1K关注 0票数 87

我最讨厌的C派生语言之一(作为一个数学家)是

代码语言:javascript
复制
(-1) % 8 // comes out as -1, and not 7

fmodf(-1,8) // fails similarly

最好的解决方案是什么?

C++允许模板和操作符重载的可能性,但这两者对我来说都是浑水摸鱼。感激不尽地收到示例。

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2010-10-23 17:25:07

首先,我想指出的是,你甚至不能依赖(-1) % 8 == -1这个事实。你唯一可以依赖的就是那个(x / y) * y + ( x % y) == x。但是,其余部分是否为负取决于实现定义。

现在为什么要在这里使用模板呢?ints和long类型的重载就可以了。

代码语言:javascript
复制
int mod (int a, int b)
{
   int ret = a % b;
   if(ret < 0)
     ret+=b;
   return ret;
}

现在你可以把它叫做mod(-1,8),它看起来是7。

编辑:我在代码中发现了一个bug。如果b是负的,它将不起作用。所以我认为这样更好:

代码语言:javascript
复制
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.

票数 77
EN

Stack Overflow用户

发布于 2010-10-23 17:15:30

下面是一个C函数,它处理两个操作数的正、负整数或小数值

代码语言:javascript
复制
#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!

测试仪代码:

代码语言:javascript
复制
#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

票数 14
EN

Stack Overflow用户

发布于 2010-11-01 11:54:40

我刚刚注意到,Bjarne Stroustrup将%标记为剩余运算符,而不是模运算符。

我敢打赌,这是它在ANSI & C++规范中的正式名称,术语的滥用已经悄然而至。有人知道这是事实吗?

但如果是这种情况,那么C的fmodf()函数(可能还有其他函数)是非常误导的。它们应该被标记为fremf(),等等

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4003232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档