找到没有条件语句的更大数字

时间:2015-02-07 20:44:34

标签: c math

我想比较两个数字“a”和“b”,如果a大于b,我想将另一个双c设置为1,否则我想将c设置为0.

以下是我到目前为止所做的事情 -

#include <stdio.h>
#include <math.h>

int main() {
    double a = 0.01242;
    double b = 0.04231;
    double c = ceil(fmod(a,b));
    //c should be 1 if a > b or else it should be 0
}

我的问题是它适用于某些数字,但通常ceil()会返回大于1的数字。

我想在不使用任何包含布尔返回类型的运算符的情况下执行此操作。

3 个答案:

答案 0 :(得分:0)

我认为您可以使用以下表达式来查找a和b之间的最大值,并使用max(a, b) ^ b找到它们是否相等然后将max(a, b) ^ b的结果赋给c。(^是按位xor)

max(a, b) = 1 / 2. * (a + b + sqrt((a - b) * (a - b)));

max(a, b) = 1 / 2. * (a + b + fabs(a-b));

我们不能在double上使用^运算符,所以如果你想使用双重跟随程序,也许可以完成你的工作:

#include <stdio.h>
#include <math.h>

double max(double a, double b)
{
    return 1 / 2. * (a + b + fabs(a-b));
}

int main(int argc, char *argv[])
{
    double b = 0.01242;
    double a = 0.04231;

    printf("%g\n", max(a, b));

    int c = ceil(max(a, b) / b);
    c = (c + 1) % c;
    /* c should be 1 if a > b or else it should be 0 */
    printf("%d\n", c);
}

答案 1 :(得分:0)

有趣的问题我解决了这个问题:

//---------------------------------------------------------------------------
double fpu_cmp(double a,double b)
    {
//  a> b -> c=1
//  a<=b -> c=0
    double c;           // a<=b     a>=b
    c=a-b;              // c<=0.0   c>0.0
    c/=fabs(c)+1e-323;  // c={-1,0} c=+1.0
    c+=fabs(c);         // c=0.0    c=+2.0
    c*=0.5;             // c=0.0    c=+1.0
    return c;
    }

//---------------------------------------------------------------------------
  • 同时处理正面和负面值
  • 如何运作在rems中解释
  • 第一列是c a<=b
  • 中的内容
  • 第二列是c a>b
  • 中的内容
  • 在时间段a,b=<-3,+3>上使用步骤0.01进行测试且没有错误
  • 如果您担心1e-323不断将1.0更改为0.99999999...9
  • 然后您仍然可以使用return ceil(c);,但我认为在当前状态下已经可以了

[注释]

  • fabs可以通过单位操作完成
  • c*=0.5只是指数递减(位掩码)
  • 所以唯一的慢操作是FPU部门
  • 1e-323只是为了避免被零除(但如果比较非常接近的数字可以显着改变结果)这个常数是避免被零除的最小值。如果你计算的数字至少比100倍大,那么你应该没问题

答案 2 :(得分:0)

在IEEE-754中,您可以将浮点值作为符号幅度整数值进行比较。所以我在这里使用它。整数比较类似于我在this answer中使用的整数比较,但是是无符号版本。以下是转换为无分支

之前的原始版本

此处减号运算符不像其他问题一样使用,但您可以通过转换回使用减号来缩短代码。

int isGreaterI(uint64_t x, uint64_t y)
{
    if ((x ^ y) >> 63) // never happens as we only pass absolute values as below
    {
        return (x >> 63) & 1;
    }
    else
    {
        uint64_t xm   = ~x + 1ULL;
        uint64_t diff = y + xm;
        return diff >> 63;
    }
}

int isGreaterF(double a, double b)
{
    uint64_t ai = *((uint64_t*)(&a));
    uint64_t bi = *((uint64_t*)(&b));
    int result;
    if ((ai ^ bi) >> 63) // different signs
    {
        result = bi >> 63; // bi < 0, ai > 0
    }
    else
    {
        uint64_t sign = ai >> 63;
        result = isGreaterI(ai, bi);
        if (sign)
            result = !result;
    }
    return result;
}

if块中复用分支的结果以删除条件并删除不必要的分支后,我们有以下最终版本

int isGreaterMagnitude(uint64_t x, uint64_t y)
{
    uint64_t xm = ~x + 1ULL;
    uint64_t diff = y + xm;
    return diff >> 63;
}

int isGreaterF(double a, double b)
{
    uint64_t ai = *((uint64_t*)(&a));
    uint64_t bi = *((uint64_t*)(&b));
    uint64_t mask = ((ai ^ bi) >> 63) + (~0ULL); // mask = 0 if a and b have different signs

    uint64_t r1 = bi >> 63;

    uint64_t sign = (int64_t)ai >> 63;
    uint64_t r2 = isGreaterMagnitude(ai, bi);
    r2 = (r2 & ~sign) | ((1 - r2) & sign);

    return (r1 & ~mask) | (r2 & mask);
}