Сравните несколько значений одновременно - PullRequest
1 голос
/ 13 февраля 2020

Мне нужно проверить, равны ли значения N.

var
  A, B, C, D : Integer;
begin
  ...
  if(A = B) and (B = C) and (C = D) then
    ShowMessage('Same value');
end;

Существует ли более короткий способ сравнения значений N? Я имею в виду что-то вроде:

var
  A, B, C, D : Integer;
begin
  ...
  if SameValue([A, B, C, D]) then
    ShowMessage('Same value');
end;

Ответы [ 3 ]

4 голосов
/ 13 февраля 2020

Что ж, лучшее, что вы можете достичь, это в основном ваше собственное предложение.

Вы бы реализовали это, используя параметр открытого массива :

function AllEqual(const AValues: array of Integer): Boolean;
var
  i: Integer;
begin
  for i := 1 to High(AValues) do
    if AValues[i] <> AValues[0] then
      Exit(False);
  Result := True;
end;

Правильность эта реализация очевидна:

  • Если число значений в массиве равно 0 или 1, возвращается True.
  • В противном случае и в общем случае возвращается False если массив содержит два неравных значения.
  • AValues[0] доступен только если High(AValues) >= 1, и в этом случае 0-е значение существует.

Функция, подобная этой, легко реализовать для порядковых типов. Для реальных типов (значений с плавающей точкой) это становится намного более тонким, по крайней мере, если вы хотите сравнить элементы с эпсилонами (как это делает функция SameValue в Delphi RTL). Действительно, тогда вы получите различное поведение в зависимости от того, сравниваете ли вы каждый элемент с первым элементом или сравниваете ли вы каждый элемент с его предшественником.

1 голос
/ 13 февраля 2020

Андреас ответил правильно, я бы хотел добавить другой подход:

uses Math;

function AllEqual(const AValues: array of Integer): Boolean;
begin
  Result := (MinIntValue(AValues) = MaxIntValue(AValues));
end;

function AllEqualF(const AValues: array of Double; Epsilon: Double): Boolean;
begin
  Result := ((MaxValue(AValues)- MinValue(AValues)) <= Epsilon);
end;
0 голосов
/ 14 февраля 2020

Существует довольно простой и очень быстрый подход сравнения равенства для целых чисел без необходимости в дополнительном методе и подобных вещах - это Битовые операторы И, конечно, это можно поместить в метод с открытым массивом или итак.

Есть даже 2 варианта (или, может быть, больше), со вторым вы также можете заменить "или" на "+", ИЛИ (не оба, это испортит логику проверки равенства c) вас может заменить «xor» на «-» (последний случай)

НО длина результирующего условия не короче оригинала (только последний случай такой же, и все скобки / скобки важны, кроме первого xor / -) Вот код тестирования:

program Project1;{$APPTYPE CONSOLE}
uses Math; var a, b, c, d, x : Integer; s: string;
begin
  Randomize;
  repeat
    x := Random(10) - 5;
    a := x + Sign(Random() - 0.5);
    b := x + Sign(Random() - 0.5);
    c := x + Sign(Random() - 0.5);
    d := x + Sign(Random() - 0.5);
    Writeln(a, ' ', b, ' ', c, ' ', d);
    Writeln((A = B) and (B = C) and (C = D));
    Writeln(a or b or c or d = a and b and c and d);
    Writeln(a xor b or (b xor c) or (c xor d) = 0);
    Writeln(a - b or (b - c) or (c - d) = 0);
    Readln(s);
  until s <> '';
end.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...