【问题标题】:Detect -1 without using a conditional statement在不使用条件语句的情况下检测 -1
【发布时间】:2021-09-22 17:26:19
【问题描述】:

您好,我在学校被问到这个问题。我似乎无法弄清楚。

不使用任何条件语句编写 c 程序 (if/else/switch:case/while/for 等) 输出:
1535(integer) 如果输入为 -1(integer)
否则输出 输入(如果不是 -1)?

问题是评估我的逻辑技能而不是 c 编程技能。

【问题讨论】:

  • 允许三元运算符吗? std::cout << (x == -1 ? 1535 : x);
  • 否则std::cout << ((x == -1) * 1535 + (x != -1) * x);
  • 什么是“输入”?它是作为命令行参数传递的字符串吗? int 传递给函数?还有什么?
  • 仅供参考,C 和 C++ 语言是不同的语言。例如,C++ 有std::stringstd::list,C 没有。由于您的作业是用 C 语言进行的,因此您可以删除 C++ 语言标签。
  • 这里对“条件语句”的定义比较宽松。我们是在谈论代码中的显式条件吗?或者我们正在谈论任何可能转换为条件分支的构造?

标签: c algorithm printf comparison-operators


【解决方案1】:

考虑:

(问题是评估我的逻辑技能而不是 c 编程技能)

我认为像“三元运算符不是条件语句”这样的语言律师是违背问题的精神的。所以让我们从完全无分支的角度来解决这个问题。

这对我来说直觉上感觉像是一项乘法工作,因为“0 吞噬一切”和“1 导致无操作”的运算属性将允许我们同时管理不同的“路径”。

换句话说,如果我们有一个神奇的函数f(),其中f(0) == 1f(anything else) == 0,那么我们可以利用x * 0 == 0x * 1 == x 的事实来“组合”这两个可能的答案:

int answer(int v) {
  int f_result = f(v + 1); // Offset the -1 to 0, which becomes 1, anything else becomes 0
  int f_inv = f(f_result); // 1 becomes 0, 0 becomes 1

  return 
     v * f_inv + 
     1535 * f_result;
}

所以,我们现在只需要一个 f(),它返回 1 表示 0,0 表示其他任何值。

这只是! 一元运算符:int f(int v) { return !v; }

【讨论】:

  • ` 像“三元运算符不是条件语句”这样的语言律师 ` - 语言律师之夜很难为这一点辩护,因为三元运算符是 条件 运算符。
  • @SergeyA 我同意,我只是想就这个问题解决 cmets。但我的措辞确实不准确。
【解决方案2】:

我可以建议以下方法

#include <stdio.h>

int main(void) 
{
    const int DEFAULT_VALUE = 1535;
    
    printf( "Enter any number or -1: " );
    
    int n = -1;
    
    scanf( "%d", &n );
    
    printf( "%d\n", ( n == -1 ) * DEFAULT_VALUE + ( n != -1 ) * n );
    
    return 0;
}

程序输出可能看起来像

Enter any number or -1: -1
1535

例如

Enter any number or -1: 10
10

程序的关键语句如下

printf( "%d\n", ( n == -1 ) * DEFAULT_VALUE + ( n != -1 ) * n );

【讨论】:

    【解决方案3】:

    救援逻辑运算符!

    int f(int v)
    {
        /*We can detect v=-1 just adding one. Next we compare it with -1 */
        /*boolean contains "1" or "0" */
        bool val= !(-1 && (v+1)); /*=1 for v=-1 */
    
        /*Finally we operate for both results of val */
        int res =  ((int) val) * 1535 + (int)(!val)*v;
    
        return res;   
     }
    

    【讨论】:

      【解决方案4】:
      1. 按位 NOT 将 (111...1) 转换为 (000...0) 为 -1(其他任何值都将为非零)
      2. 逻辑非将 (000....0) 转换为 1(以及任何其他转换为 0)
      3. 乘以 1535

      这是一个测试所有整数的完整 C 程序:

      #include <stdio.h>
      #include <limits.h>
      
      int result(int value)
      {
          return (!(~value))*1535;
      }
      
      void check(int input, int expected)
      {
          if (result(input) != expected)
              printf("Result was %d for input %d (expected: %d)\n", result(input), input, expected);
      }
      
      int main()
      {
          for (int i = INT_MIN; i > -1; ++i)
              check(i, 0);
          for (int i = 0; i < INT_MAX; ++i)
              check(i, 0);
      
          check(INT_MAX, 0);
          check(-1, 1535);
      }
      

      Live Demo


      Bonus C++ demo(因为问题最初是这样标记的):

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-04
        • 1970-01-01
        • 2013-12-25
        相关资源
        最近更新 更多