Laden...

Wie am elegantesten einen Wert innerhalb eines Zahlenbereiches vergleichen?

Erstellt von aken0 vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.088 Views
A
aken0 Themenstarter:in
8 Beiträge seit 2014
vor 9 Jahren
Wie am elegantesten einen Wert innerhalb eines Zahlenbereiches vergleichen?

Guten tag,

ich möchte in einem Programm den BMI ausgerechnet haben und zusätzlich als Ausgabe, in welchem Bereich sich dieser findet.

Beispiel:
BMI zwischen 19 & 24 -> normales Gewicht
BMI zwischen 25 & 28 -> leichtes übergewicht

Mir ist natürlich klar, wie ich ein Wert innerhalb diesen Bereich ausfindig machen kann,
nur finde ich, wenn ich das mit mehreren if/else if Abfragen löse, das es "unsauber" wirkt. Gibt es einer elegantere Möglichkeit eine Zahl in mehreren Zahlenbereichen ausfindig zu machen?

1.346 Beiträge seit 2008
vor 9 Jahren

Hallo aken0,

Viel elleganter als


if(value < 19) return Untergewicht;
else if(value < 25) return normales Gewicht;
else if(value < 29) return leichtes Übergewiccht;
else return Übergewicht;

wirst du das nicht hinbekommen. Ich sehe da aber auch kein Problem drin.

Lieben Gruß,
pdelvo

F
10.010 Beiträge seit 2004
vor 9 Jahren

naja, wenn man es nicht gerade für soetwas simples wie den BMI macht, und das evt Regelbasiert haben will, macht man sich halt entsprechende klassen.


public class BmiRange
{
  public string Name{get;protected set;}
  public int LowRange{get;protected set;}
  public int HigRange{get;protected set;}

  public BmiRange(string name, int low, int high)
  {
    Name = name;
    LowRange=Math.Min(low,high);
    HighRange=Math.Max(low,high);
  }

  public bool Contains(int value)
  {
      return (value >=LowRange) && ( value <= HighRange);
  }
}

.
.
var bmiList = new List<BmiRange>()
{
  new BmiRange("magersucht",0,19),
  new BmiRange("Normal",19,25),
  new BmiRange("Big",25,30),
  new BmiRange("Healthy",30,32),
  new BmiRange("Huski",32,34),
  new BmiRange("Fluffy",34,38),
  new BmiRange("Damn",38,60)
}

.
.
.

BmiRange currentBMI = bmiList.Find(bmi=>bmi.Contains(aktuellerWert));
.
.



Aber ob das statt der 4 zeilen eleganter ist???

P
157 Beiträge seit 2014
vor 9 Jahren

Bau dir ne Extension oder benutz operatorenüberladungen , fluent interfaces, Specifications(ein sehr nützliches Pattern für regelbasierende system/workflows und co) oder oder oder 😉

public static bool Between(this int cmpValue, int min, int max) { return ... ; }

Elegant ist was gefällt ... ich persönlich bevorzuge den direkten weg, mein Code soll sich wie eine Geschichte lesen. Der Teufel liegt nämlich im Detail und alles was nach : "if(a<b && a>c) then do this and this else a = 2" oder ähnliche programm-code-exoten aussieht, versteht man nämlich nach spätestens 2 Monaten selbst nicht mehr, ohne nachdenken zu müssen, was man sich da mal(s) ausgedacht hat.

vg

Wenn's zum weinen nicht reicht, lach drüber!

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo pdelvo,

durch die Verwendung von return braucht man kein else. Das macht es nochmal etwas übersichtlicher:


if(value < 19) return "Untergewicht";
if(value < 25) return "normales Gewicht";
if(value < 29) return "leichtes Übergewicht";
return "Übergewicht";

****Hallo zusammen,

aus meiner Sicht gibt es drei Aspekte, die man berücksichtigen sollte:

  1. Die BMI-Bereiche sind zusammenhängend. Wenn man tatsächlich so fragen würde, wie es in der Aufgabenstellung formuliert ist,

if(value ≥ 19 && value ≤ 24) return "normales Gewicht";
if(value ≥ 25 && value ≤ 29) return "leichtes Übergewicht";

dann hätte man mit den BMI-Werten größer 24 und kleiner 25 ein Problem, denn BMI-Werte sind üblicherweise gebrochene Zahlen. Man sollte also tatsächlich besser so abfragen, wie pdelvo vorgeschlagen hat (nur ohne else).

Nicht mit if auf Unter- und Obergrenze, nicht mit LowRange/HighRange und nicht mit Between. Selbst wenn man die jeweils folgende Untergrenze aus ihrer vorigen Obergrenze konstruieren würde, müsste man immer noch aufpassend, dass die eine Grenze inklusive und die andere exklusive sein muss (also < und ≥. Oder ≤ und >). Alles unnötig kompliziert ...

  1. ... womit wir bei dem KISS-Prinzip sind. Eine if-Kette ist trotz oder gerade wegen ihrer Simplizität für jeden Leser des Programmcodes leicht zu verstehen. Was zukünftige Erweiterungen angeht, die eine aufwändigere Konstruktion rechtfertigen könnten, gibt gerade bei BMI wohl YAGNI.

  2. Bleiben noch die magic numbers direkt im ausführbaren Code. Man könnte überlegen, diese als symbolische Konstanten oder als Enum zu definieren. Oder man lagert sie ganz aus dem Code aus, als Ressource(nwerte) oder als (Konfiguratiosns-)Datei. Man kann sich natürlich darüber streiten, ob das hier notwendig ist. Und wenn man die Zahlenwerte auslagert, dann müsste man eigentlich auch die zugehörigen String-Werte in gleicher Art und Weise auslagern.

herbivore