Fabrizio
Fabrizio

Reputation: 8043

Compare multiple values at a time

I need to check if N values are equals.

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

Is there a shorter way to compare N values? I mean something like:

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

Upvotes: 2

Views: 1522

Answers (3)

Vlad Fomin
Vlad Fomin

Reputation: 21

There is quite simple and very fast equality comparison approach for ints without a need of additional method and stuff like this - it's Bitwise Operators And of course, this could be put in a method with open array or so.

There are even 2 options (or maybe more), with second you also can replace "or" to "+" , OR (not both, it will ruin equality-test logic) you can replace "xor" to "-" (last case)

BUT the resulting condition length is not shorter than original (only the last case is same and all brackets/parenthesis are vital, except first xor/-), here is the testing code:

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.

Upvotes: 0

Guest
Guest

Reputation: 11

Andreas' answer is correct, I'd like to add a different approach though:

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;

Upvotes: 1

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108963

Well, the best you can achieve is basically your own suggestion.

You would implement this using an open array parameter:

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;

The correctness of this implementation is obvious:

  • If the number of values in the array is 0 or 1, it returns True.
  • Otherwise, and in general, it returns False iff the array contains two non-equal values.
  • AValues[0] is only accessed if High(AValues) >= 1, in which case the 0th value exists.

A function like this one is straightforward to implement for ordinal types. For real types (floating-point values), it becomes much more subtle, at least if you want to compare the elements with epsilons (like the SameValue function does in the Delphi RTL). Indeed, then you get different behaviour depending on if you compare every element against the first element, or if you compare every element against its predecessor.

Upvotes: 4

Related Questions