【问题标题】:How to get the correct value of / and % operators?如何获得 / 和 % 运算符的正确值?
【发布时间】:2013-05-29 09:09:51
【问题描述】:

我想做以下事情:

我使用变量int a 来保留来自控制台的输入,然后执行以下操作:

int b = a / 16;

a 是64 或32 时,我得到4 或2。但如果a 是63,我希望得到4,但我得到3。C 中有什么方法可以得到四舍五入的值吗?

编辑。更多详情:

rang 1 to 16 should get 1,
rang 17 to 32 should get 2,
rang 33 to 48 should get 3,
rang 49 to 64 should get 4

【问题讨论】:

  • 你想要什么? round(a / 16.0),四舍五入:(a + 15)/16?
  • 或四舍五入到最接近的(a + 8)/16)(对于正值a)?
  • 你不是“假设”得到 4 个。出于某种原因,你想要 4 个,但是当你将 63 个玩具分配给 16 个孩子时,每个孩子得到 3 个。
  • @user2131316...如果a = 61,60 会有什么结果?
  • @user2131316.../16 已修复或可以更改为任何数字 -> a / 5,a / 13,... ?

标签: c operator-keyword


【解决方案1】:

当您将除法运算符/ 与两个int 参数一起使用时,它将返回一个代表截断结果的int

您可以在不使用浮点数的情况下进行四舍五入除法,如下所示:

int a;
int den = 16;
int b = (a + den - 1) / den;

这会给你你所期望的:

a ∈      [0], b =        0 / 16 = 0,
a ∈  [1, 16], b = [16, 31] / 16 = 1,
a ∈ [17, 32], b = [32, 47] / 16 = 2,
a ∈ [33, 48], b = [48, 63] / 16 = 3,
a ∈ [49, 64], b = [64, 79] / 16 = 4,
...

请注意,这仅在ab 为正数时才有效,并注意a + den 可能的溢出。 如果怀疑a + den 可能溢出,那么您可以使用此表达式的另一个版本:

int b = (a - 1) / den + 1;

唯一的缺点是它会在a = 0 时返回1。如果这是一个问题,您可以添加类似的内容:

int b = (a - 1) / den + 1 - !a;

请注意,您也可以以相同的方式处理 a 的负值(从零四舍五入):

int b = (a > 0) ? (a - 1) / den + 1 : (a - den + 1) / den;

【讨论】:

    【解决方案2】:

    C 中的整数除法/ 不执行roding,而是执行truncation

    【讨论】:

    • @user2131316 请参阅 Lundin 和 praks411 的答案,了解使用浮点除法和舍入的方法。请参阅我的答案,了解使用简单整数除法的方法。
    【解决方案3】:

    解决方案

    int ans, newNo;
    int no = 63; // Given number
    int dNo = 16; // Divider
    
    newNo = (no % dNo) ? (dNo - (no % dNo) + no) : no; // Round off number
    
    ans = newNo / dNo;
    

    编辑

    优化解决方案

    ans = (no / dNo) + !!(no % dNo);

    【讨论】:

    • 你可以写ans = no/dNo + !!(no%dNo);来避免分支
    • @zakinster...thanx 的建议。
    【解决方案4】:

    无论您尝试什么在概念上都不正确,但如果您想要与您在问题中所说的相同的结果,您可以尝试在 math.h 中定义的标准函数 double ceil(double x)

    向上舍入x,返回不小于x的最小整数值。

    【讨论】:

      【解决方案5】:

      得到你想要的最简单的方法是使用浮点数。

      #include <math.h>
      #include <stdio.h>
      
      int main(void) 
      {
        double a = 63.0;
        double b = 16.0;
      
        printf("%d", (int) round(a / b));
      
        return 0;
      }
      

      从浮点数转换为整数时要小心,反之亦然。例如,round(63/16) 不正确。它返回一个双精度值,但什么也没做,因为文字 63 和 16 是整数。除法是在将值传递给函数之前完成的。正确的方法是确保一个或两个操作数都是 double 类型:round(63.0 / 16.0)

      【讨论】:

      • 最简单的方法? (int)round(a/(double)b)真的比(a+b-1)/b简单吗?
      • 将一个非常简单的整数解决方案更改为浮点解决方案并不是一个好主意。它的性能更差(浮点运算),更容易出错(就像你在答案中所说的那样)并且更不便携(在内核代码或微控制器中并不总是可能)。
      • 另外,只有80位的double可以存储64位的int而不会丢失精度。
      【解决方案6】:

      你可以试试下面的

       int b = (int)ceil((double)a/16);
      

      【讨论】:

        【解决方案7】:

        由于 C int 除法总是向零舍入,因此可以用来使其均匀舍入的一个简单技巧是在舍入之前将“0.5”添加到数字上。例如,如果要除以 32,请使用

        x = (a+16)/32;
        

        或更一般地,对于 a/b,其中 a 和 b 都是正数:

        x = (a+b/2)/b;
        

        不幸的是,负数会使它有点复杂,因为如果结果是负数,那么你需要减去 0.5 而不是加上它。如果您在编写代码时已经知道它是正面的还是负面的,那没问题,但是如果您同时处理正面和负面的答案,它就会变得混乱。你可以这样做......

        x = (a+((a/b>0)?1:-1)*(b/2)) / b;
        

        但到了那个阶段,它开始变得相当复杂 - 最好只转换为 float 并使用 round 函数。

        --

        [Edit] 正如 zakinster 指出的那样,尽管问题要求“圆形”值,但给出的示例实际上需要 ceil。使用整数的方法是:

        x = (a+b-1)/b;
        

        同样,如果答案可能是否定的,这将变得复杂:

        x = (a+((a/b>0)?1:-1)*(b-1)) / b;
        

        如果有人感兴趣,我会保留我的原始回复以进行四舍五入。

        【讨论】:

        • 他不想,他想ceil,看OP。
        猜你喜欢
        • 2015-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-29
        • 1970-01-01
        • 2018-10-06
        相关资源
        最近更新 更多