Как вернуть true или false без использования операторов отношения в c?

Для развлечения предположим, что мы хотим сравнить два числа формата double, используя язык c, и мы можем использовать только математические уравнения, которые используют арифметические операторы +, -, *, /, %, fabs() и pow() для проверки равенства (==), меньше (<), и больше (>). Подобно реальным реляционным операторам ==, <, and >, код, который мы пишем, должен возвращать True (1) или False (0) для каждого из различных типов проверок.

Например, без использования каких-либо других операторов, кроме +, -, *, /, %, fabs() и pow(), если мы определяем, что две переменные a и b равны, мы должны вернуть True или 1, в противном случае вернуть False или 0. Это лучше возвращать целые числа 0 и 1 вместо логических значений True и False. Чтобы усложнить ситуацию, мы не можем использовать настоящие реляционные операторы, логические операторы, побитовые операторы или любые другие операторы. Кроме того, мы не можем использовать операторы переключения или условные операторы. Как это сделать?

Я знаю, как найти меньшее значение x и y, то есть x < y можно вычислить как ((x + y) + fabs(x-y))/2. Далее, чтобы найти x > y, это ((x + y) - fabs(x-y))/2. Однако эти уравнения возвращают значение x или y в зависимости от уравнения сравнения, и мне нужно, чтобы они возвращали 0 или 1. Точно так же мне нужно некоторое уравнение кода, которое возвращает 0 или 1, если x и y равны (==) каждому другое и должно делать это, используя только +, -, *, /, %, fabs() и pow().


person Chris Heady    schedule 03.02.2019    source источник
comment
Вам разрешено использовать такие функции, как abs()?   -  person Barmar    schedule 04.02.2019
comment
@ Бармар, да, ты можешь использовать abs( ).   -  person Chris Heady    schedule 04.02.2019
comment
Я не знаю, как это сделать, но разве весь смысл этого не в том, чтобы ты сам во всем разобрался?   -  person Barmar    schedule 04.02.2019
comment
Нет, потому что я не учусь в классе. Поэтому я не могу спросить инструктора. И я думал, что я спрошу ТАК. И меня мучает то, что я не могу этого понять.   -  person Chris Heady    schedule 04.02.2019
comment
Если он возвращает x или 0, то как насчет деления на x?   -  person user253751    schedule 04.02.2019
comment
@immibis 0/0 недействителен.   -  person Barmar    schedule 04.02.2019
comment
Я хотел бы выразить результат следующим образом (time1==time2)*2 + (time1>time2)*2 + (time1<time2)*1 и просто добавить новые уравнения, которые я создаю для ==, › и ‹.   -  person Chris Heady    schedule 04.02.2019
comment
Можете ли вы использовать логическое отрицание (!)? Если можно, !(a-b) эквивалентно a==b.   -  person pmg    schedule 04.02.2019
comment
Нет, к сожалению только +, -, *, /, and %.   -  person Chris Heady    schedule 04.02.2019
comment
Цифры double? unsigned? int? Больше, чем 0? Между 3.14 и 3.15?   -  person pmg    schedule 04.02.2019
comment
@pmg, они double.   -  person Chris Heady    schedule 04.02.2019
comment
Вы не можете использовать % с double ... просто говорю :)   -  person pmg    schedule 04.02.2019
comment
Можно ли использовать ^, |, ! и &?   -  person Bob Jarvis - Reinstate Monica    schedule 04.02.2019
comment
@BobJarvis, нет, мы не можем использовать ^, |, ! и &.   -  person Chris Heady    schedule 04.02.2019
comment
Если pow разрешено, вы можете проверить равенство с pow(0.0, fabs(x - y)), предполагая соглашение pow(0.0, 0.0) == 1. Затем x > y можно протестировать с x == max(x, y).   -  person nwellnhof    schedule 04.02.2019
comment
@nwellnhof Я думаю, что pow() разрешено, просто позвольте мне еще раз проверить инструкции. Но разве max() не вернет значение x или y? Если да, то я не думаю, что это сработает в данном случае. Мне нужен max(), который возвращает только значение 0 или 1.   -  person Chris Heady    schedule 04.02.2019
comment
Да, pow( ) разрешено.   -  person Chris Heady    schedule 04.02.2019


Ответы (1)


Любой из заданных операторов +, -, *, /, примененный к double операндам, приведет к double, а также к функциям fabs() и pow(). Таким образом, невозможно преобразовать double в integer, используя только предоставленные операторы и функции fabs() и pow().

Кроме того, оператор % предназначен только для целых чисел. Существует функция 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.0 и 1.9999993 ведут себя хорошо, но 2.0 и 1.9999994 считаются равными, несмотря на то, что 32-битное число с плавающей запятой может представлять значения 1.9999993 и 1.9999994, и оба они отличимы от 2.0.

person Denis Golovkin    schedule 04.02.2019