Warum verhält sich die NMIN()-Funktion komisch?

Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV
12 Beiträge • Seite 1 von 1
12 Beiträge Seite 1 von 1

Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von DeathAndPain (Top Expert / 1991 / 270 / 418 ) »
Hallo zusammen,

folgender Code:

Code: Alles auswählen.

REPORT ztest3.

DATA: w1(4) TYPE p DECIMALS 2,
      w2(4) TYPE p DECIMALS 2,
      result(4) TYPE p DECIMALS 2.

START-OF-SELECTION.

w1 = '4'.
w2 = '219'.

result = nmin( val1 = 100 * w1 / w2 val2 = 100 ).

WRITE result.
Warum ist das ausgegebene Ergebnis 0,00?!? 100*4/219 ist bei mir 1,83 (und damit kleiner als 100), und dieser Wert sollte (ebenso wie alle etwaigen Zwischenwerte bei der Berechnung) problemlos in ein P-Feld der Länge 4 mit zwei Dezimalstellen reinpassen. NMIN scheint irgendwie mit Integer zu rechnen und daher abzurunden, aber der Doku zufolge dürfte das nicht sein, denn die besagt, dass ein Rechentyp bestimmt wird und dieser als TYPE P festgelegt wird, wenn irgendwo in der Formel ein TYPE P-Wert vorkommt (und keine TYPE F-Werte dabei sind).

Finde ich sehr schräg. Hat jemand eine Erklärung?

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von a-dead-trousers (Top Expert / 4471 / 228 / 1203 ) »
Sehr spannend.
Erfolgt die Berechnung außerhalb von NMIN funktioniert es wie erwartet.
Ich hab auch noch versucht alle 100er durch Variablen vom Typ P zu ersetzen aber auch das hat nichts gebracht.
Hab somit leider aber auch keine Erklärung dafür.

P.S.: Basis Release 7.50

EDIT: Mit Variablen vom Typ F funktioniert es übrigens wiederum. Meine Vermutung ist daher, dass das Packed-Format (Type P) diesen Fehler auslöst. Dazu müsste man sich vermutlich tiefer in die Geschichte von SAP und seinem tollen P einlesen.

Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag (Insgesamt 2):
rob_abcDeathAndPain

Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von DeathAndPain (Top Expert / 1991 / 270 / 418 ) »
Bei dem von mir verwendeten System war es Release 7.40. Aber wie Du schon richtig sagst, passiert der Fehler ohne NMIN nicht. NMIN gab es zwar schon vor 7.40 (ist also kein Teil der neuen Syntax), aber dennoch würde ich daraus schlussfolgern, dass es sich um einen Bug handelt - zumal die Online-Dokumentation des Befehls explizit erläutert, auf welche Weise der intern verwendete Datentyp ermittelt werden sollte (aber offenbar nicht wird, es sei denn, NMIN verwendet einen TYPE P DECIMALS 0, was ziemlich witzlos wäre; dann können sie auch gleich i verwenden. Macht aber auch irgendwie keinen Sinn, denn wenn man die Berechnung vorher macht und nur die Ergebnisse als Felder dem NMIN übergibt, arbeitet er korrekt).

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von Radinator (ForumUser / 86 / 13 / 7 ) »
In unserem System it SAP BASIS 7.57 wenn ich den Code ausführe, dann kommt ebenfalls 0,00 raus. Ich hab dann etwas rumexperimentiert und geschaut ob vlt es an der "order of operation" liegt (also ob Klammern setzen was bringt), Resultat: Nö. Auch mit "korrekter" Notation/Verwendung der Klammern kommt 0,00 raus.
Wenn ich die Berechnung in einer dritten Variable mache (oder w1 als Ziel verwende), dann kommt der richtige Wert raus -> wie schon berichtet scheint die Funktion selber 'n "Feature" zu haben ;)
Nächster Versuch mit CONV p( ) resultierte in einer Compilermeldung Ein Wert des generischen Typs "P" kann nicht konstruiert werden.. Wenn ich aus dem P ein F mache, dann funktioniert die Konversion und als Resultat kommt 1,83 raus.
Edit: Verwendung von TYP F in der Variablendeklaration für w1 und w2, TYPE P LENGTH 4 DECIMALS 2 für result gibt mir ebenfalls 1,83 (bei F für alle 3 Variablen ist das Ergebnis logischerweise ein 1,83...E+00)

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von DeathAndPain (Top Expert / 1991 / 270 / 418 ) »
Radinator hat geschrieben:Nächster Versuch mit CONV p( ) resultierte in einer Compilermeldung Ein Wert des generischen Typs "P" kann nicht konstruiert werden.
Ohne es probiert zu haben, würde ich sagen, das hängt damit zusammen, dass P für sich betrachtet kein vollständiger Typ ist. Du kannst ja auch kein Feld einfach nur mit

Code: Alles auswählen.

DATA feldname TYPE p.
deklarieren. Was nach meiner Erwartung nach funktionieren sollte, wäre

Code: Alles auswählen.

TYPES: vier_dec_2(4) type p decimals 2.

...

result = nmin( val1 = conv vier_dec_2( 100 * w1 / w2 ) val2 = conv vier_dec_2( 100 ) ).
Insofern ist (nach meiner Erwartung) nicht P als Datentyp das Problem, sondern die Verwendung im CONV.

Dennoch sollte zumindest der erste meiner beiden CONVs unnötig sein und in der erweiterten Programmprüfung deswegen angemeckert werden. Wie gesagt, ist jetzt alles Theorycrafting, kann grad kein Beispiel durchtesten.

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von a-dead-trousers (Top Expert / 4471 / 228 / 1203 ) »
Mit der Konvertierung innerhalb der Funktion funktioniert es auch.

Spannend ist auch, dass das funktioniert:

Code: Alles auswählen.

DATA result TYPE F.
result = nmin( val1 = 100 * 4 / 219 val2 = 100 ).
WRITE result. "1,8264840182648401E+00
Aber diese Variante funktioniert nicht:

Code: Alles auswählen.

DATA result TYPE p length 4 DECIMALS 2.
result = nmin( val1 = 100 * 4 / 219 val2 = 100 ).
WRITE result. "0.00
Somit wäre ich wieder bei meiner ursprünglichen Vermutung, dass schlicht nur das P in diesem Kontext nicht (korrekt) funktioniert.
Interessant wäre also was am Datentyp P (der ja intern etwas anders arbeitet als z.B. F oder I) hier den Ausschlag für dieses Verhalten gibt. Auch eine "Verlängerung" (z.b. 10/4) bringt keine Ändeurung obwohl das oft als "Allheilmittel" für Probleme mit der "Genauigkeit" von P gilt.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von a-dead-trousers (Top Expert / 4471 / 228 / 1203 ) »
ChatGPT hat geschrieben:Warum steht „0.00“ im Ergebnis?

Weil der Ausdruck nicht in Fließkommaarithmetik, sondern in Dezimalarithmetik erfolgt, sobald das Ziel ein PACKED-Feld ist.

Viele erwarten, dass 100 * 4 / 219 erst in Float berechnet wird → aber das ist falsch.

ABAP konvertiert die Operanden schrittweise in PACKED.
Dabei kann ein Zwischenschritt 0 ergeben (wegen zu kleiner Genauigkeit).

Beispielhafte interne Schritte:

100 * 4 → PACKED → 400

400 / 219 → PACKED Division
PACKED-Zahlen haben begrenzte interne Stellenanzahl → Ergebnis wird zu
1.00… mit abgeschnittenen Nachkommastellen, oder sogar 0, abhängig von der Version & Optimizer.

Am Ende bekommt nmin möglicherweise:

val1 = 0
val2 = 100

Und nmin( 0 , 100 ) = 0.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von a-dead-trousers (Top Expert / 4471 / 228 / 1203 ) »
ChatGPT hat geschrieben:Merksatz

In ABAP richtet sich die Arithmetik nicht nach dem Ausdruck, sondern nach dem Datentyp der Operanden (und oft auch des Zieltyps).
PACKED führt streng dezimale Arithmetik aus und kann sehr leicht Zwischenwerte abschneiden oder auf 0 runden.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von black_adept (Top Expert / 4149 / 133 / 958 ) »
Um weiter zu verwirren mal folgendes Programm ausführen. Wer diese Ausgabe ( zumindest auf einem 7.4 SP10 System ) vorhergesehen hat bekommt den Titel ABAP-Guru.

Code: Alles auswählen.

REPORT.


DATA  ergebnis TYPE p LENGTH 4 DECIMALS 2.
DATA: teiler TYPE i.

DO 219 TIMES.
  teiler = 220 - sy-index.
  ergebnis = nmin( val1 = 100 * 4 / teiler val2 = 100 ).
  WRITE:/ teiler, ergebnis.
ENDDO.

Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag:
a-dead-trousers

live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von a-dead-trousers (Top Expert / 4471 / 228 / 1203 ) »
😂 😂 😂

Der Vergelcih zwischen den beiden Datentypen ist auch sehr aussagekräftig:

Code: Alles auswählen.

REPORT.

DATA  ergebnis1 TYPE f.
DATA  ergebnis2 TYPE p LENGTH 4 DECIMALS 2.
DATA: teiler TYPE i.

DO 219 TIMES.
  teiler = 220 - sy-index.
  ergebnis1 = nmin( val1 = 100 * 4 / teiler val2 = 100 ).
  ergebnis2 = nmin( val1 = 100 * 4 / teiler val2 = 100 ).
  WRITE:/ teiler, ergebnis1, ergebnis2.
ENDDO.
Immer dann, wenn die Nachkommastellen den P "sprengen", wird das Ergebnis 0.
Wobei hier vermutlich die max. Ausprägung von 14 Nachkommastellen für P relevant ist, da z.B. 3,125 als 3,13 funktioniert hat.

EDIT: Ich könnte mir vorstellen, dass es innerhalb der Berchnung zu einem "Loss of Precision"-Fehler kommt der "silent" abgefangen wird, weil das an dieser Stelle nicht sein darf. Im Gegensatz dazu ist bei einer Zuweisung (MOVE) dieser Verlust in ABAP explizit erlaubt und sogar entsprechend dokumentiert.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von Radinator (ForumUser / 86 / 13 / 7 ) »
Intressant ist auch, dass bei teiler = 3 die Rechnung 100 * 4 /3 laut MS Taschenrechner 133,333... ergibt, die Rechnung in ABAP in das Float Feld 1,000...E+02 und das P-Feld 100,00 hat xD

Re: Warum verhält sich die NMIN()-Funktion komisch?

Beitrag von DeathAndPain (Top Expert / 1991 / 270 / 418 ) »
adt hat geschrieben:PACKED-Zahlen haben begrenzte interne Stellenanzahl
Wie wenig Stellen sollen das bitte sein, dass das bei meiner Berechnung schon gesprengt wird?!? Ich finde die Frage viel spannender, wie viele DECIMALS er bei seiner internen Berechnung verwendet. Bisher macht es ja den Anschein, als ob er mit DECIMALS 0 rechnet. Dann wären wir mathematisch aber bei Integerzahlen (und die interne Länge kann so lang sein, wie sie will). Ein absolut bescheuertes Verhalten von ABAP, IMHO.

Seite 1 von 1

Vergleichbare Themen

5
Antw.
6875
Views
Funktionsbausteine - FUNKTION/FUNKTION TOOL
von kafka » 06.02.2018 08:04 • Verfasst in ABAP® für Anfänger
1
Antw.
2274
Views
Objekttyp <> Objekttyp .....komisch
von danielA. » 16.05.2006 11:35 • Verfasst in ABAP® Core
5
Antw.
3729
Views
Funktion CO 24 ???
von Pinguincommander » 23.08.2013 08:38 • Verfasst in Material Management & Produktionsplanung
3
Antw.
2734
Views
Funktion POPUP_TO_CONFIRM
von kaim77 » 07.03.2013 12:37 • Verfasst in ABAP® für Anfänger
2
Antw.
2310
Views
Filter bei ALV-Funktion
von ibo » 18.11.2016 13:29 • Verfasst in ABAP® für Anfänger

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.