【发布时间】:2009-05-18 07:14:06
【问题描述】:
在没有任何条件或比较运算符的情况下执行以下操作。
if (Number <= 0)
{
Print '0';
}
else
{
print Number;
}
谢谢..
【问题讨论】:
在没有任何条件或比较运算符的情况下执行以下操作。
if (Number <= 0)
{
Print '0';
}
else
{
print Number;
}
谢谢..
【问题讨论】:
我原来的简单解决方案:
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)
)
【讨论】:
print max(0, number)
【讨论】:
假设这个数字由一个 8 位二进制补码整数表示。
包括0的正数都将MSB设置为0。
负数都将 MSB 设置为 1。
所以我们取 MSB 的补码,将其扩展到完整的 8 位,然后与原始数字按位与,例如
正面:
00110101 -> MSB 为 0
11111111 -> 扩展 MSB 的补码
00110101 -> 上述按位与
否定:
10110101 -> MSB 为 1
00000000 -> 扩展 MSB 的补码
00000000 -> 上述的按位与
不需要比较 - 我有点假设按位与并不是严格的比较。
另外,很抱歉缺少代码,但你明白了。
【讨论】:
我还没有看到对整个域有效的解决方案。
另一种解决方案是,如果输入值为 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原则呢。
【讨论】:
类似于接受的答案。虽然在使用比较实现绝对值的情况下可以接受,但也更容易溢出:
print((sqrt(Number * Number) + x) / 2);
【讨论】:
假设 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);
【讨论】: