在没有条件比较的情况下在数学上找到最大值

Posted

技术标签:

【中文标题】在没有条件比较的情况下在数学上找到最大值【英文标题】:Mathematically Find Max Value without Conditional Comparison 【发布时间】:2010-11-25 10:36:46 【问题描述】:

---------更新了------------

到目前为止,codymanix 和 moonshadow 提供了很大的帮助。我能够使用方程式解决我的问题,而不是使用右移除以 29。因为 32 位有符号 2^31 = 溢出到 29。哪个有效!

php 中的原型

$r = $x - (($x - $y) & (($x - $y) / (29)));

LEADS 的实际代码(每行只能执行一个数学函数!!!啊啊啊!!!)

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 或条件检查。

有没有办法使用上面的有限操作来找到一个非常接近最大值的值?

【问题讨论】:

你可以使用按位运算吗? "现在如果 A 总是大于 B,那么找到最大值会很简单" Ummm... A? 为什么有人给出这个问题-1?这个问题没有错。但是你应该告诉你正在使用哪种编程语言。 我可以执行的唯一操作是 (/, *, +, -, &, |, !) 我不能进行按位移位。我给出的例子是任意数字和变量。我不会知道信息的值,当然只是变量名。我正在使用一种未记录的自定义脚本语言,用于处理天气数据,在本例中为雷达。 只是好奇:在这种情况下,您处于哪种类型的炼狱中?我们能把比尔盖茨关在那里吗? 【参考方案1】:

如果我们设法找到两个数字之间的差异,我想这将是最简单的(只有大小没有符号)

max = ((a+b)+|a-b|)/2;

其中|a-b|ab 之间的差异幅度。

【讨论】:

这个答案非常有帮助。它还把我带到了min = ((a+b)-|a-b|)/2。非常感谢!【参考方案2】:

finding the maximum of 2 variables:

max = a-((a-b)&((a-b)>>31))

其中 >> 是按位右移(也称为 SHR 或 ASR,取决于符号)。

您使用数字的位数减一,而不是 31。

【讨论】:

+1 请注意,这仅适用于 32 位。如果数字是 8/16/64 位 - 需要相应地更改“31”。 如果不允许轮班: int max(int a, int b) int c = a - b; int d = c & 0x7000;整数 e = d * -1;整数 f = e + 1;诠释 g = f & 0x1;返回 (g * a) | ((g*-1) * b); 我使用了不同的变量,所以你可以看到每一步发生了什么。 在 C 中,不需要符号扩展,IIRC,因此您的代码可能无法正常工作。此外,为了更便携,请将 31 替换为 sizeof(type)*8-1。 @codymanix:一种未记录的脚本语言,通过称为 LEADS 的天气应用程序使用。 右移负数行为取决于实现,如图here【参考方案3】:

如果您不能信任您的环境在可用时生成适当的无分支操作,请参阅this page 了解如何继续。注意输入范围的限制;如果您不能保证您的输入适合,请使用更大的整数类型。

【讨论】:

【参考方案4】:

没有条件的解决方案。转换为 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); 

【讨论】:

在C中,这个abs (a)a < 0时不返回绝对值。【参考方案5】:

仅使用逻辑运算、短路评估并假设 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 那样遵循向底值取整的约定,则可以执行类似的技巧。

【讨论】:

我确实尝试过实现这个方法,但没有达到预期的效果。这确实帮助我弄清楚我的值没有被四舍五入,而是被转换为双精度值。啊! 它将相对于零 (-c;c) 对的对称转换为相对于零对 (1;0) 对的不对称。这是通过嵌入舍入约定的隐式if 完成的。 a == b时不起作用【参考方案6】:
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;

【讨论】:

这是什么语言?自然语言?漂亮你只使用初等运算符 几年前我有一个计算器,它允许存储简单的公式,但没有条件或函数,如 abs 或 min/max。我希望我当时就知道这一点,有很多可能性。 @Et7f3XIV 这看起来像 Pascal 编程语言。【参考方案7】:

嗯。我假设 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

因此,将给出更大位的索引。因此,比较两个数字中的每个位,当它们不同时,使用上面的表达式(不是 A 和 B)来确定哪个数字更大。从最高有效位开始并向下处理两个字节。如果您没有循环结构,请手动比较每个位。

实现“当它们不同时”:

(A != B) AND(我的逻辑在这里)

【讨论】:

如果没有 shift(并且知道类型的大小(以字节为单位)),就无法做到这一点。 是的,你可以。只需使用 2**bit_index 即可获得您的比较数字。 记住“shift”只是乘以/除以2。 如果为真,有没有办法在没有条件的情况下实现“当它们不同时”? 但如果移位涉及符号位,我的建议中就是这种情况(>>31)【参考方案8】:

试试这个,(但要注意溢出) (C#代码)

    public static Int32 Maximum(params Int32[] values)
    
        Int32 retVal = Int32.MinValue;
        foreach (Int32 i in values)
            retVal += (((i - retVal) >> 31) & (i - retVal));
        return retVal;        
    

【讨论】:

【参考方案9】:

您可以将其表示为一系列算术和按位运算,例如:

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;

【讨论】:

myabs(-6) 和 myabs(6) 给出 -6。所以它应该是 return (in ^ tmp) - tmp;【参考方案10】:
//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;


【讨论】:

【参考方案11】:

这是我仅使用 +, -, *, %, / 运算符的实现

using static System.Console;

int Max(int a, int b) => (a + b + Abs(a - b)) / 2;
int Abs(int x) => x * ((2 * x + 1) % 2);

WriteLine(Max(-100, -2) == -2); // true
WriteLine(Max(2, -100) == 2);   // true

【讨论】:

【参考方案12】:

我只是想出了一个表达式: (( (a-b)-|a-b| ) / (2(a-b)) )*b + (( (b-a)-|b-a| )/(2(b-a)) )*a 如果 a>b 则等于 a,如果 b>a

则等于 b

当 a>b 时: a-b>0, a-b = |a-b|, (a-b)-|a-b| = 0 所以 b 的系数是 0

b-a<0, b-a = -|b-a|, (b-a)-|b-a| = 2(b-a) 所以a的系数是2(b-a)/2(b-a),即1 所以如果 a 更大,它最终会返回 0*b+1*a,反之亦然

【讨论】:

【参考方案13】:

在 n 和 m 之间找到 MAX

MAX = ( (n/2) + (m/2) + ( ((n/2) - (m/2)) * ( (2*((n/2) - (m/2)) + 1) % 2) ) )
在c中使用#define:
#define MAX(n, m) ( (n/2) + (m/2) + ( ((n/2) - (m/2)) * ( (2*((n/2) - (m/2)) + 1) % 2) ) )
#define ABS(n) ( n * ( (2*n + 1) % 2) )  // Calculates abs value of n
#define MAX(n, m) ( (n/2) + (m/2) + ABS((n/2) - (m/2)) )  // Finds max between n & m
#define MIN(n, m) ( (n/2) + (m/2) - ABS((n/2) - (m/2)) )  // Finds min between n & m

【讨论】:

【参考方案14】:

请看看这个程序..这可能是迄今为止此页面上最好的答案...

#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;

【讨论】:

【参考方案15】:

如果 A 总是大于 B .. [我们可以使用] .. MAX = (A - B) + B;

不需要。只需使用:int maxA(int A, int B) return A;

(1) 如果允许使用条件语句,您可以使用max = a&gt;b ? a : b

(2) 任何其他方法要么使用一组定义的数字,要么依赖于隐式条件检查。

(2a) max = a-((a-b)&amp;((a-b)&gt;&gt;31)) 这很简洁,但它只适用于 if 你使用 32 位数字。您可以将其扩展为任意大数 N,但如果您尝试找到 max(N-1, N+1),该方法将失败。该算法适用于有限状态自动机,但不适用于图灵机。

(2b) 幅度|a-b| 是一个条件|a-b| = a-b&gt;0 a-b : b-a

怎么样:

平方根也是一个条件。每当c&gt;0c^2 = d 我们有第二个解决方案-c,因为(-c)^2 = (-1)^2*c^2 = 1*c^2 = d。平方根返回配对中的最大值。我有一个构建在int max(int c1, int c2)return max(c1, c2);

如果没有比较运算符,数学是非常对称的并且功率有限。如果没有某种if,就无法区分正数和负数。

【讨论】:

其实sqrt没有第二解,不是针对特定的输入,sqrt是一个函数:brilliant.org/wiki/plus-or-minus-square-roots【参考方案16】:
using System;
namespace ConsoleApp2

    class Program
    
        static void Main(string[] args)
        
            float a = 101, b = 15;
            float max = (a + b) / 2 + ((a > b) ? a - b : b - a) / 2;            
        
    

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票 问题要求没有条件比较的解决方案。这 ?运算符是条件比较。【参考方案17】:

这取决于您使用的语言,但Ternary Operator 可能有用。

但是,如果您无法在“脚本应用程序”中执行条件检查,您可能没有三元运算符。

【讨论】:

我确定他们不能使用 if,他们不能使用 ?: 要么 该语言中没有可用的条件语句。 @Brian,这就是我所说的,但被否决了。也许答案中也不允许使用条件语句。【参考方案18】:
#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

【讨论】:

完全不相关,并且对于数组中的最大数量效率低下。

以上是关于在没有条件比较的情况下在数学上找到最大值的主要内容,如果未能解决你的问题,请参考以下文章

你可以在没有显式引用或所有权移动的情况下在结构上实现数学操作吗?

如何在没有连接的情况下在自关联中使用条件?

如何在不更改声音指示器的情况下在 iOS 中以最大音量播放声音文件

在给定条件的情况下查找列表的最小和最大索引

如何在没有 ipad 的情况下在纵向和横向条件下测试 ipad 网站?

最大熵模型