【问题标题】:Finding the middle number out of three (without if-else and such)找出三个中的中间数(没有 if-else 等)
【发布时间】:2021-02-17 21:55:53
【问题描述】:

我被要求编写一个包含 3 个数字的短程序,并打印中间的一个 即 3 2 0 ->“中间数为 2” 另一个例子:4 4 5 -> 中间的数字是 4(用户可以输入两次相同的数字

使用 if 函数会很容易,但是

  • 我不允许使用条件或循环

编辑:不能使用数组 我试图将数字相互除以得到一个 0,表示一个更大或更小

【问题讨论】:

  • 使用大小为 3 的数组来存储输入,并在完成后打印 array[1] 的值。
  • 你尝试过什么?我们不能只为你的作业问题提供解决方案。
  • 另外,“中间”是指输入的第二个还是第二个最小/最大的?
  • 中间的意思是按大小..不是输入@Peter的顺序
  • 从您的 cmets @Lostdawn 看来,限制似乎比您在问题中描述的要多。我建议将整套要求编辑到问题中,尤其包括对您可以使用的运算符的任何限制,以及对必须支持的输入数字范围的任何要求。

标签: c algorithm if-statement conditional-statements


【解决方案1】:

使用比 int 更宽的数学来处理范围限制。

通过除法求绝对值。1

((3 * d) / (3 * d + 1)) -->  0 when d >= 0
((3 * d) / (3 * d + 1)) --> -1 when d < 0

没有使用条件。

long long my_abs_diff(long long a, long long b) {
  long long d = 0LL + a - b;
  return d * (1 - 2 * ((3 * d) / (3 * d + 1)));
}

long long my_min(long long a, long long b) {
  return ((a + b) - my_abs_diff(a, b)) / 2;
}

long long my_max(long long a, long long b) {
  return ((a + b) + my_abs_diff(a, b)) / 2;
}

int median3(int a, int b, int c) {
  long long mn = my_min(my_min(a, b), c);
  long long mx = my_max(my_max(a, b), c);
  return (int) (-mn - mx + a + b + c);
}

可能存在简化。


1在 C 中,从 C99 开始,整数除法被定义为向零截断。正是这种对零代码的定向性被利用来实现“如果”。这种方法的代价是我们需要更多的整数范围位。对于 C99 之前的版本,代码可以使用 div() 来确保所需的商截断。

在整个int 范围内使用许多边缘情况和 10,000,00,00 个随机组合成功测试:[INT_MIN ... INT_MAX]。

【讨论】:

    【解决方案2】:

    使用这两个函数:

    int maximum(int a, int b, int c)
    {
        // initialize max with a
        int max = a;
        
        // set max to b if and only if max is less than b
        (max < b) && (max = b); // these are not conditional statements.
        
        // set max to c if and only if max is less than c
        (max < c) && (max = c); // these are just Boolean expressions.
    
        return max;
    }
    
    int minimum(int a, int b, int c)
    {
        // initialize min with a
        int min = a;
        
        // set min to b if and only if min is more than b
        (min > b) && (min = b);
        
        // set min to c if and only if min is more than c
        (min > c) && (min = c);
        
        return min;
    }
    

    然后可以使用以下方法轻松计算中间值:

    (a+b+c)-minimum(a, b, c)-maximum(a, b, c)
    

    编辑:

    要在不定义任何函数的情况下运行代码,我们可以使用以下代码。它和上面的完全一样,但是所有的工作都在 main 函数中。

    int main() {
        int a=3, b=2, c=0, min, max;
    
        // initialize min with a
        min = a;
    
        // set min to b if and only if min is more than b
        (min > b) && (min = b);
    
        // set min to c if and only if min is more than c
        (min > c) && (min = c);
    
        // similarly find max
        max = a;
        (max < b) && (max = b);
        (max < c) && (max = c);
    
        printf("%d", a+b+c-min-max);
        return 0;
    }
    

    【讨论】:

    • 有没有办法在主程序中找到最小最大值?我们没有被教导做副业,我宁愿不这样做
    • 该问题明确指出“无条件”,而在您的回答中 - (max &lt; b) &amp;&amp; (max = b) - 有 3 个逻辑条件(假设您的意思是 == ,否则此代码甚至无法正常工作)。
    • , ==, != 这些被称为“关系”运算符。通过“无条件”,我认为这意味着没有 if-else,也没有 condition?statement1:statement2; 类型语句。我已经检查过代码工作正常。诀窍是,如果&amp;&amp; 左边的语句返回 1(true),那么只有右边的语句才会被执行。
    • @SohamSaha,虽然&lt;&gt; 是关系运算符,但问题在于&amp;&amp;。该标准将其称为“逻辑运算符”,而不是“条件运算符”,但将其用作if 语句的替代品似乎至少违反了禁止条件语句的精神。尽管如此,这可能正是预期的结果,但还有其他方法更清楚地符合规则(据我了解)。
    【解决方案3】:

    正如almost duplicate question 和之前的回答中提到的,一种方法是将三个值相加,然后减去最小值和最大值。

    但是,使用库的minmax 函数有点作弊,因为很可能使用了内部条件。

    一种方法是使用关系:

    min(a, b) = (a + b - abs(a-b))/2;
    max(a, b) = (a + b + abs(a-b))/2;
    

    等等

    评论中提到使用abs 也是作弊。 在实践中,我不知道它内部是如何实现的。

    一种可能性是使用这篇文章中提到的技巧:get absolute values...

    例如,abs(a) = sqrt (a*a);

    【讨论】:

    • 范围限制:abs(a-b)a-b 溢出或a-b == INT_MIN 时失败。当a &gt; sqrt(INTMAX) 时,sqrt (a*a) 失败。
    • @chux-ReinstateMonica 当然可以。我认为在这样的理论练习中它并不重要。我提到的链接提出了abs 的更好解决方案。我想让解决方案尽可能简单
    【解决方案4】:

    提示:首先使用 std::min 和 std::max 找到最小值和最大值
    然后将所有数字相加并减去最小值和最大值。 剩下的是中间值。

    【讨论】:

    • 从未听说过 std::min 或 max 答案应该是简单的除法乘法 sub/add 等
    • 这个问题在 C 语言中,无论如何,这两个函数都使用条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多