【问题标题】:Interview qns...Do the below without any conditional or comparison operator采访 qns...在没有任何条件或比较运算符的情况下执行以下操作
【发布时间】:2009-05-18 07:14:06
【问题描述】:

在没有任何条件或比较运算符的情况下执行以下操作。

if (Number <= 0)
{
    Print '0';
}
else
{
    print Number;
}

谢谢..

【问题讨论】:

    标签: algorithm math


    【解决方案1】:

    我原来的简单解决方案:

    1. print( (abs(Number)+Number) / 2 )
    

    该解决方案在大多数情况下都有效,除非 Number 非常大(超过最大值的一半,例如 Number >= MAX_INT/2),在这种情况下,加法可能会导致溢出。

    以下方案解决溢出问题:

    2. print( (abs(Number)/2) + (Number/2) )
    

    但是,在某些情况下,Number 是并且必须保持整数,并且除法运算符 (/) 是整数除法,因此 7/2=3。在这种情况下,解决方案 2 将不起作用,因为如果 Number=7 它将打印 6(对于这种情况,解决方案 1 可以正常工作)。

    因此,如果我们需要同时处理大数和整数运算,那么下面的怪物会来救援,为奇数情况下除以 2 时可能丢失的 1 添加补偿:

    3. print( 
        ( (abs(Number)/2)+(Number/2) ) +
        ((
            (Number-(2*(Number/2))) + 
            (abs(Number)-(2*(abs(Number)/2)))
        ) / 2)
        )        
    

    【讨论】:

    • @malach:溢出是什么意思?
    • Number+Number > 对应类型的最大值
    • 如果 Number 是奇数,除法会导致数据丢失或转换成双倍。 Print 要么不打印数字而是数字 1,要么根据语言使用十进制数字或其他浮点表示形式打印它。
    • 我实际上假设这个数字是浮点数,因为没有提到整数限制。
    【解决方案2】:
    print max(0, number)
    

    【讨论】:

    • 在 C/C++ 中,这类似于 print (number
    • 好的,但适用于 PHP、Ruby、Python、Java、C# 等,语法略有不同。
    • 如果是比较而不是内置函数,那么sign()和abs()也是。
    • C/C++中max和min是宏,由预编译器扩展,abs是math.h中的函数,所以有区别。
    • 我的最后一条评论是对现在已删除的评论的回应,作者声称函数 max() 可以算作任何语言的比较 - 我知道这将是 C/ 中的比较C++,但问题没有说明任何语言。
    【解决方案3】:

    假设这个数字由一个 8 位二进制补码整数表示。

    包括0的正数都将MSB设置为0。

    负数都将 MSB 设置为 1。

    所以我们取 MSB 的补码,将其扩展到完整的 8 位,然后与原始数字按位与,例如

    正面:

    00110101 -> MSB 为 0

    11111111 -> 扩展 MSB 的补码

    00110101 -> 上述按位与

    否定:

    10110101 -> MSB 为 1

    00000000 -> 扩展 MSB 的补码

    00000000 -> 上述的按位与

    不需要比较 - 我有点假设按位与并不是严格的比较。

    另外,很抱歉缺少代码,但你明白了。

    【讨论】:

    • +1 整数的出色解决方案,而不是浮点数。我只是喜欢二进制数学:)
    【解决方案4】:

    我还没有看到对整个域有效的解决方案。

    另一种解决方案是,如果输入值为 0 或低于 0,则调用引发异常的函数。然后捕获异常并打印 0。

    或者你可以使用一个函数Sign,如果输入为

    print ((sign(x)+1) * sign(x) / 2) * x.
    

    sign 可以是 -1、0 或 1,因此 ((sign(x)+1) * sign(x) / 2) 可以有以下值:

    -1 -> ((-1+1)*-1)/2 = 0
     0 -> ((0+1)*0)/2 = 0
     1 -> ((1+1) * 1)/2  = 1
    

    另一种方法是创建一个查找表,将所有非负数映射到自己,其余的映射到 0。

    但是,在我看来,原来的功能要清晰得多。那么为什么要违反KISS原则呢。

    【讨论】:

    • 因为是面试题 :) 肯定给他们指出来(原来的功能更清晰),但他们想测试你的聪明才智什么的,而不是你的编码原则。
    • 我知道,但有时他们希望您回答他们不问的问题。此外,如果你在面试时表现得聪明一点也不会有害,除非你不这样做。
    【解决方案5】:

    类似于接受的答案。虽然在使用比较实现绝对值的情况下可以接受,但也更容易溢出:

    print((sqrt(Number * Number) + x) / 2);

    【讨论】:

      【解决方案6】:

      假设 C 或 C++:

      switch ((unsigned long)Number & ~(unsigned long)LONG_MAX) {
          case 0:
              printf("%d\n", Number);
              break;
          default:
              printf("0\n", Number);
              break;
      }
      

      如果你认为 switch 是一个条件运算符,那么试试这个:

      unsigned long flag = (unsigned long)Number & ~(unsigned long)LONG_MAX;
      flag /= (unsigned long)LONG_MAX + 1;
      flag = 1 - flag;
      printf("%d\n", Number * flag);
      

      【讨论】:

      • 我会考虑 switch 一个经典的比较
      • switch/case 语句不会满足“没有任何条件或比较运算符”的要求吗?
      • switch 不是运算符。这是一个声明。
      • 是的,IF 也是一个语句,但它是一个条件语句。 en.wikipedia.org/wiki/Conditional_statement
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      相关资源
      最近更新 更多