Ответ 1
max = a-((a-b)&((a-b)>>31))
где → - побитовый сдвиг вправо (также называемый SHR или ASR, основанный на подписи).
Вместо 31 вы используете количество бит, у ваших номеров минус один.
---------- Обновлено ------------
codymanix и moonshadow были большой помощью до сих пор. Я смог решить свою проблему, используя уравнения, вместо того, чтобы использовать правый сдвиг, который я разделил на 29. Потому что с 32 битами, подписанными 2 ^ 31 = переполнение до 29. Что работает!
Прототип в PHP
$r = $x - (($x - $y) & (($x - $y) / (29)));
Фактический код для LEADS (вы можете выполнять только одну математическую функцию PER LINE!!! AHHHH!!!)
DERIVDE1 = IMAGE1 - IMAGE2;
DERIVED2 = DERIVED1 / 29;
DERIVED3 = DERIVED1 AND DERIVED2;
MAX = IMAGE1 - DERIVED3;
---------- Оригинальный вопрос -----------
Я не думаю, что это вполне возможно с ограничениями для моих приложений, но я решил, что стоит попробовать.
Я постараюсь сделать это простым. Мне нужно найти максимальные значения между двумя числами, не имея возможности использовать IF или любой условный оператор.
Чтобы найти значения MAX, я могу выполнять только следующие функции
Divide, Multiply, Subtract, Add, NOT, AND ,OR
Скажем, у меня два числа
A = 60;
B = 50;
Теперь, если A всегда больше B, было бы просто найти максимальное значение
MAX = (A - B) + B;
ex.
10 = (60 - 50)
10 + 50 = 60 = MAX
Проблема: A не всегда больше B. Я не могу выполнять ABS, MAX, MIN или условные проверки с помощью скриптового приложения, которое я использую.
Можно ли использовать ограниченную операцию выше, чтобы найти значение ОЧЕНЬ близко к максимальному?
max = a-((a-b)&((a-b)>>31))
где → - побитовый сдвиг вправо (также называемый SHR или ASR, основанный на подписи).
Вместо 31 вы используете количество бит, у ваших номеров минус один.
Я думаю, это было бы самым простым, если нам удастся найти разницу между двумя числами (только величина не знака)
max = ((a+b)+|a-b|)/2;
где |a-b|
- величина разницы между a
и b
.
Если вы не можете доверять своей среде для создания соответствующих нераспределенных операций, когда они доступны, см. эту страницу для продолжения. Обратите внимание на ограничение на диапазон ввода; используйте более крупный целочисленный тип для операции, если вы не можете гарантировать, что ваши входы будут соответствовать.
Решение без условностей. Отправляйтесь в uint, затем обратно в int, чтобы получить abs.
int abs (a) { return (int)((unsigned int)a); }
int max (a, b) { return (a + b + abs(a - b)) / 2; }
int max3 (a, b, c) { return (max(max(a,b),c); }
Используя только логические операции, оценку короткого замыкания и предположение о приближении С к нулю, можно выразить это как:
int lt0(int x) {
return x && (!!((x-1)/x));
}
int mymax(int a, int b) {
return lt0(a-b)*b+lt0(b-a)*a;
}
Основная идея состоит в том, чтобы реализовать оператор сравнения, который будет возвращать 0 или 1. Это может сделать подобный трюк, если ваш язык сценариев следует за соглашением округления к значению пола, как это делает python.
Хммм. Я предполагаю, что NOT, AND и OR побиты? Если это так, для решения этого вопроса должно быть побитовое выражение. Заметим, что A | B даст число >= A и >= B. Возможно, существует метод обрезки для выбора числа с наибольшим количеством бит.
Чтобы расширить, нам нужно следующее, чтобы определить, больше ли A (0) или B (1).
таблица истинности:
0|0 = 0
0|1 = 1
1|0 = 0
1|1 = 0
!A and B
следовательно, даст индекс большего бита. Ergo, сравнивайте каждый бит в обоих числах, а когда они разные, используйте указанное выше выражение (Not A и B), чтобы определить, какое число было больше. Начните с самого значащего бита и опустите оба байта. Если у вас нет петлевой конструкции, вручную сравнивайте каждый бит.
Реализация "когда они разные":
(A!= B) И (моя логика здесь)
попробуйте это (но помните о переполнениях) (Код в С#)
public static Int32 Maximum(params Int32[] values)
{
Int32 retVal = Int32.MinValue;
foreach (Int32 i in values)
retVal += (((i - retVal) >> 31) & (i - retVal));
return retVal;
}
function Min(x,y:integer):integer;
Var
d:integer;
abs:integer;
begin
d:=x-y;
abs:=d*(1-2*((3*d) div (3*d+1)));
Result:=(x+y-abs) div 2;
end;
Вы можете выразить это как серию арифметических и поразрядных операций, например:
int myabs(const int& in) {
const int tmp = in >> ((sizeof(int) * CHAR_BIT) - 1);
return tmp - (in ^ tmp(;
}
int mymax(int a, int b) {
return ((a+b) + myabs(b-a)) / 2;
}
посмотрите эту программу.. это может быть лучшим ответом до даты на этой странице...
#include <stdio.h>
int main()
{
int a,b;
a=3;
b=5;
printf("%d %d\n",a,b);
b = (a+b)-(a=b); // this line is doing the reversal
printf("%d %d\n",a,b);
return 0;
}
//Assuming 32 bit integers
int is_diff_positive(int num)
{
((num & 0x80000000) >> 31) ^ 1; // if diff positive ret 1 else 0
}
int sign(int x)
{
return ((num & 0x80000000) >> 31);
}
int flip(int x)
{
return x ^ 1;
}
int max(int a, int b)
{
int diff = a - b;
int is_pos_a = sign(a);
int is_pos_b = sign(b);
int is_diff_positive = diff_positive(diff);
int is_diff_neg = flip(is_diff_positive);
// diff (a - b) will overflow / underflow if signs are opposite
// ex: a = INT_MAX , b = -3 then a - b => INT_MAX - (-3) => INT_MAX + 3
int can_overflow = is_pos_a ^ is_pos_b;
int cannot_overflow = flip(can_overflow);
int res = (cannot_overflow * ( (a * is_diff_positive) + (b *
is_diff_negative)) + (can_overflow * ( (a * is_pos_a) + (b *
is_pos_b)));
return res;
}
Это зависит от того, какой язык вы используете, но может оказаться полезным Ternary Operator.
Но тогда, если вы не можете выполнять условные проверки в своем "скриптовом приложении", у вас, вероятно, нет тернарного оператора.
Если A всегда больше B.. [мы можем использовать]..
MAX = (A - B) + B;
Нет необходимости. Просто используйте: int maxA(int A, int B){ return A;}
(1) Если условия разрешены, вы выполняете max = a>b ? a : b
.
(2) Любой другой метод использует либо определенный набор чисел, либо полагается на неявные условные проверки.
(2a) max = a-((a-b)&((a-b)>>31))
это аккуратно, но работает только if
. Вы используете 32-битные номера. Вы можете развернуть его произвольным большим числом N, но метод будет терпеть неудачу, если вы попытаетесь найти max (N-1, N + 1). Этот алгоритм работает для автоматов с конечным состоянием, но не для тюнинговой машины.
(2b) Величина |a-b|
является условием |a-b| = a-b>0 a-b : b-a
Квадратный корень также является условием. Всякий раз, когда c>0
и c^2 = d
, мы имеем второе решение -c
, потому что (-c)^2 = (-1)^2*c^2 = 1*c^2 = d
. Квадратный корень возвращает наибольшее значение в паре. Я прихожу со сборкой int max(int c1, int c2){return max(c1, c2);}
Без сравнения операторная математика очень симметрична, а также ограничена по мощности. Положительные и отрицательные числа нельзя отличить без if
.
#region GetMaximumNumber
/// <summary>
/// Provides method to get maximum values.
/// </summary>
/// <param name="values">Integer array for getting maximum values.</param>
/// <returns>Maximum number from an array.</returns>
private int GetMaximumNumber(params int[] values)
{
// Declare to store the maximum number.
int maximumNumber = 0;
try
{
// Check that array is not null and array has an elements.
if (values != null &&
values.Length > 0)
{
// Sort the array in ascending order for getting maximum value.
Array.Sort(values);
// Get the last value from an array which is always maximum.
maximumNumber = values[values.Length - 1];
}
}
catch (Exception ex)
{
throw ex;
}
return maximumNumber;
}
#endregion