如何在不使用 c 中的关系运算符的情况下 return true 或 false?

How to return true or false without using the relational operators in c?

娱乐一下,假设我们要用c语言比较格式为double的两个数字,而我们只能使用使用算术运算符+, -, *, /, %和[=13=的数学方程式] 和 pow() 以检查等于 (==)、小于 (<) 和大于 (>)。与真正的关系运算符 ==, <, and > 类似,我们编写的代码必须 return True (1) 或 False (0) 用于每种不同类型的检查。

例如,没有使用除+, -, *, /, %fabs()pow()以外的任何其他运算符,如果我们确定两个变量ab 相等,我们应该 return True 或 1,否则,return False 或 0。最好是 return 整数 0 和 1 而不是布尔值 True 和 False。更复杂的是,我们不能使用真正的关系运算符、逻辑运算符、位运算符或任何其他运算符。此外,我们不能使用 switch 语句或条件语句。如何操作?

我知道如何求x和y中较小的值,也就是说x < y可以计算为((x + y) + fabs(x-y))/2。进一步,要找到x > y,就是((x + y) - fabs(x-y))/2。但是,这些方程 return 值 x 或 y 取决于比较方程,我需要它们 return 0 或 1。同样,我需要一些代码方程 return 是 0 或1 如果 x 和 y 彼此相等 (==),并且必须仅使用 +, -, *, /, %fabs()pow().

任何给定的运算符 +, -, *, / ,应用于 double 操作数将导致 double,以及 fabs()pow() 函数。因此无法仅使用提供的运算符和 fabs()pow() 函数将 double 转换为 integer

此外,% 运算符仅适用于整数。有一个 fmod() 函数,它为浮点数提供相同的功能。

我们可以实现我们的计算结果,仅使用提供的运算符和函数将以相同的方式在内存中表示为整数 0 和 1。

例如,这些函数是为 float 制作的,即 32 位浮点数:

float largerOf(float x, float y){
    return ((x + y) + fabs(x-y)) / 2.0;
}

float smallerOf(float x, float y){
    return ((x + y) - fabs(x-y)) / 2.0;
}

int isEqual(float x, float y){
    float tmp = smallerOf(x, y) / largerOf(x, y);
    tmp /= 3.4028235E38;
    tmp /= 4194303.9999999997;
    return *((int*)(&tmp));
}

int lessThan(float x, float y){
    float tmp = smallerOf(x, y) / x;
    tmp /= 3.4028235E38;
    tmp /= 4194303.9999999997;
    return (*((int*)(&tmp)))-isEqual(x,y);
}

int greaterThan(float x, float y){
    float tmp = smallerOf(x, y) / y;
    tmp /= 3.4028235E38;
    tmp /= 4194303.9999999997;
    return (*((int*)(&tmp)))-isEqual(x,y);
}

这个解决方案使用了这样一个事实,即两个值中较小的值除以两个值中的较大值将导致小于或等于 1.0 的值。然后,当且仅当第一次除法的结果恰好为 1.0 时,除法后的结果值再次除以两个硬编码常量,以尝试获得最右边位设置的浮点数。毕竟,我们访问内存,包含浮点数,就好像它包含整数结果一样。


请注意,此解决方案未经过充分测试,可能会以多种不同方式出现问题。例如,值 2.01.9999993 表现良好,但是 2.01.9999994 被认为是相等的,尽管 32 位浮点数可以表示值 1.99999931.9999994 并且它们都与 2.0 不同。