比较两个整数并在两个数字之间插入比较符号<,> =

时间:2016-02-21 03:57:36

标签: c math

我想比较两个正整数,并在它们之间添加一个比较符号。我不能使用任何logicalrelationalbitwise operatorsif,然后elsewhile循环或三元运算符。

我找到了这两个数字的maxmin

  

如何保留订单并仍然插入比较符号?有任何想法吗?

E.g:

用户输出输入的

4 6必须为4 < 6

用户输出输入的

10 2必须为10 > 2

用户输出输入的

2 2必须为2 = 2

f1 = x / y;
f2 = y / x;

f1 = (f1 + 2) % (f1 + 1);
f2 = (f2 + 2) % (f2 + 1);

max = f1  * x + f2 * y ;
max = max / (f1 + f2); 

4 个答案:

答案 0 :(得分:5)

您可以使用char数组:

#include <stdio.h>

int main(void)
{
    unsigned a, b;
    scanf("%u %u", &a, &b);

    size_t cmp = (_Bool)(a / b) - (_Bool)(b / a);
    char relation = "<=>"[cmp + 1];
    printf("%u %c %u\n", a, relation, b);

    return 0;
}

此方法不需要minmax

说明:

    如果(_Bool)exp非零,则
  1. exp将为1;如果exp等于0,则<0>。{/ li>
  2. 由于ab是正整数,a / ba < b时为0,在a >= b时为1。有关详细信息,请参阅下面的真值表。
  3.         (_Bool)(a / b)    (_Bool)(b / a)     (_Bool)(a / b) - (_Bool)(b / a)
    
    a > b          1                 0                          1
    
    a = b          1                 1                          0
    
    a < b          0                 1                         -1
    
    1. 因此,cmp评估为-1, 0, 1,就像典型的比较函数一样。因此,cmp + 1将方便地导致0, 1, 2有效的数组索引。
    2. 感谢@janos his help

      编辑:

      正如@chux小心指出的那样,

        OP表示“我可能不使用任何逻辑,...运算符”。 C规范有   “......逻辑否定运算符!......”。 §6.5.3.35。使用!不得   符合OP的目标。

      所以我将!!exp更改为(_Bool)exp以满足OP的要求。

      编辑II:

      OP评论道:

        

      感谢。当其中一个输入为0时,这不起作用。

      但是,输入数字不是正面的吗?好吧,要处理零,您可以使用size_t cmp = (_Bool)((a + (_Bool)(a - UINT_MAX)) / (b + (_Bool)(b - UINT_MAX))) - (_Bool)((b + (_Bool)(b - UINT_MAX)) / (a + (_Bool)(a - UINT_MAX)));。不要忘记#include <limits.h>

      编辑III(最后的编辑,我希望):

      #include <stdio.h>
      #include <limits.h>
      
      #define ISEQUAL(x, y) (_Bool)((_Bool)((x) - (y)) - 1) // 1 if x == y, 0 if x != y
      #define NOTEQUAL(x, y) (_Bool)((x) - (y)) // 0 if x == y, 1 if x != y
      
      int main(void)
      {
          unsigned a, b;
          printf("%u\n", UINT_MAX);
          scanf("%u %u", &a, &b);
      
          _Bool hasZero = NOTEQUAL(ISEQUAL(a, 0) + ISEQUAL(b, 0), 0);
          _Bool hasMax = NOTEQUAL(ISEQUAL(a, UINT_MAX) + ISEQUAL(b, UINT_MAX), 0);
          int hasBoth = ISEQUAL(hasZero + hasMax, 2);
          int cmp = (_Bool)((a + hasZero + hasBoth) / (b + hasZero + hasBoth))\
                  - (_Bool)((b + hasZero + hasBoth) / (a + hasZero + hasBoth));
          // "+ hasZero + hasBoth" to avoid div 0: UINT_MAX -> 1, while 0 -> 2.
          hasBoth =  1 - hasBoth * 2; // 1 if hasBoth == 0, or -1 if hasBoth == 1
          char relation = "<=>"[hasBoth * cmp + 1]; // reverse if has both 0 and UINT_MAX
          printf("%u %c %u\n", a, relation, b);
      
          return 0;
      }
      
      1. 修正了@chux指出的== UINT_MAX - 1和b == UINT_MAX指出的错误。
      2. 使用宏来提高可读性。
      3. 添加了一些评论。

答案 1 :(得分:4)

由于OP有xy并已计算出其最低min和最高max

void prt(unsigned x, unsigned y, unsigned min, unsigned max) {
  // min not used
  unsigned cmp = 1 + x/max - y/max;
  printf("%u %c %u\n", x, "<=>"[cmp],  y);
}

答案 2 :(得分:1)

#include <stdio.h>
static unsigned int cmpgt(const unsigned int a, const unsigned int b)
{
    return b?(a/b ? (a-b):0):a;
    // if B is 0, then return A. non zero A will be treated as true
    //            if a is zero then is false
    // if b is not zero then do a/b, if non zero then return (a-b)
    //            non zero (a-b) will be treated as true
    //            if (a-b) is zero then will be treated as false
    //
    // This is a very ugly way of implementing operator >
    // There are other ways to do it
    // But the point is, you need operator >, but you can not use it
    // ( for whatever reason), then you just make it, which is doable
}
static const char *mark(const unsigned int a, const unsigned int b)
{
    return cmpgt(a, b)?">":(cmpgt(b,a)?"<":"=");
    // no if-else, but ternary operator is a good alternative
    // so those are two nested operator ?:
    // basically :
    // if a>b then return ">"
    // else if a<b return "<"
    // else return "="
    // with cmpgt/operator > implemented, this is a lot easier          
}
int main(void) {
    const int input[] = {1,3,4,5,5,2,3,4}; //test input
    size_t input_size = sizeof(input)/sizeof(int);
    for (size_t i=0;cmpgt(input_size-1, i);i++){
        // while loop is banned, but for loop is still usable
        // the loop condition is handled by cmpgt
        printf("%d %s ",input[i],mark(input[i], input[i+1]));
    }
    printf("%d\n", input[input_size-1]);
    return 0;
}

示例输出:

1 < 3 < 4 < 5 = 5 > 2 < 3 < 4

https://ideone.com/dFHWnn

答案 3 :(得分:0)

一个简单的比较是使用<=>=,然后从字符串中查找比较字符。

void cmp1(unsigned x, unsigned y) {
  int cmp = (x >= y) - (x <= y);
  printf("%u %c %u\n", x, "<=>"[cmp + 1],  y);
}

然而,由于我们不能使用各种运算符等,我们需要做的就是替换>=

_Bool foo_ge(unsigned x, unsigned y) {
  _Bool yeq0 = 1 - (_Bool)y;        // y == 0?
  _Bool q = (x + yeq0)/(y + yeq0);  // Offset both x,y, by yeq0
  return q + yeq0;
}

void cmp2(unsigned x, unsigned y) {
  int cmp = foo_ge(x,y) -  foo_ge(y,x)
  printf("%u %c %u\n", x, "<=>"[cmp + 1],  y);
}

大量使用_Bool赠送给@sun qingyao