TIA Die Potenz hat eine negative Basis - Potenz (**) mit negativer Basis?

Geroldicer

Level-1
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich soll eine mir zuvor unbekannte Zahl potenzieren. Natürlich kann diese Zahl auch negativ sein. Also z.B.: (-2)^3=-8. Bei negativen Zahlen als Basis erhalte ich jedoch die Fehlermeldung "Die Potenz hat eine negative Basis", und das Programm wird nicht übersetzt. Bei Variablen erhalte ich zur Laufzeit bei negativem Basis-Aktualwert das Ergebnis NON (Not a Number 16#7FF). Wie kann also im Tia / Simatic eine negative Zahl potenziert werden?

Zur Info: Auch die oft gelistete Funktion/ Umweg über die Logarithmusfunktion hilft in diesem Fall nichts: Hab dazu den AWL-Code in SCL umgesetzt:
#LRealValue3 := EXP_LREAL(IN:=(LN(#LREALValue1)) * #LREALValue2); -> gleiches Ergebnis, nur dass diese Funktion im Gegensatz zur Verwendung von ** auch noch beim Basiswert 0 als Ergebnis NON liefert..

(AWL Quelle war: https://support.industry.siemens.com/tf/WW/de/posts/potenzrechnung/21218?page=0&pageSize=10 )
 
Mal so als erste Überlegung:

Kannst du nicht einfach bei einer negativen Zahl das Vorzeichen umkehren (z.B. * -1), dann potenzieren und das Vorzeichen wieder umkehren (*-1).

Die Abfrage, ob die Geschichte mit dem Vorzeichen gemacht werden muss, wäre ja eigentlich nur, "Eingegebene Zahl kleiner 0".

Gruß

Chris
 
Hallo,
der Logarithmus von 0 ist nicht definiert. Darum kommt NaN heraus.
Vielleicht hilft Dir folgender Ansatz.

log v/u = - log u/v

log 2/-1 = -log 1/2

Gruß Frank
 
Hallo,
der Logarithmus von 0 ist nicht definiert. Darum kommt NaN heraus.
Vielleicht hilft Dir folgender Ansatz.

log v/u = - log u/v

log 2/-1 = -log 1/2

Gruß Frank

Habs für negative Basen getestet:
#LReal3 := EXP_LREAL(IN := (- LN(1 / ABS_LREAL(#LREAL1))) * #LREAL2);

..funktioniert soweit, jedoch verschwindet das Vorzeichen, und alle Ergebnisse sind positiv.. also gleiches Problem wie beim Vorzeichen-Abfangen wie oben vorgeschlagen..
 
Zuletzt bearbeitet:
Schau mal in deinem Posteingang

Gruß Chris

Danke! Mir ist die Abfrage der "Hochzahl mit Kommastelle" nicht ganz klar.. So wie ich das verstehe, wird da bei allen positiven Kommazahlen gerechnet wie bei negativem Ergebnis, bei allen negativen Kommazahlen so wie bei positivem Ergebnis? -> [Edit]: Beitrag #13 klärt dies auf

Meine Implementierung sieht momentan folgendermaßen aus (ohne die Hochzahl Abfrage auf Kommastellen):

Code:
IF #pIO_Base.lrValue > 0.0 THEN
    #pIO_Result.lrValue := EXP_LREAL(IN := (LN(#pIO_Base.lrValue)) * #pIO_Exp.lrValue);
ELSIF #pIO_Base.lrValue < 0.0 THEN
    #pIO_Result.lrValue := EXP_LREAL(IN := (- LN(1 / ABS_LREAL(#pIO_Base.lrValue))) * #pIO_Exp.lrValue);
    IF (TRUNC(#pIO_Exp.lrValue) MOD 2) > 0 THEN
        #pIO_Result.lrValue *= LREAL#-1;
    END_IF;
ELSIF
   #pIO_Exp.lrValue = 0.0 THEN
   #pIO_Result.lrValue := 1.0;
ELSE
    #pIO_Result.lrValue := 0.0;
END_IF;

..Einwände / Verbesserungsvorschläge erwünscht..
 
Zuletzt bearbeitet:
Es gilt Folgendes:

Potenzen mit einer negativen Grundzahl (Basis) sind positiv, wenn die Hochzahl gerade ist.
Potenzen mit einer negativen Grundzahl (Basis) sind negativ, wenn die Hochzahl ungerade ist.



Code:
// Überprüfen ob Hochzahl gerade oder ungerade ist

// Zahl mit Kommastelle
      O(
      L     "Hochzahl"
      TRUNC
      ITD
      DTR
      L     "Hochzahl"
      -R
      L     0.0
      <R
      )

// Ungerade Zahl
      O(
      L     "Hochzahl"
      TRUNC
      L     2
      MOD
      T     #Temp_Hochzahl
      L     0
      >I
      )
      SPB   Neg

Also schaue ich erst mal, ob es sich um eine Kommazahl handelt. Der Grund, warum ich die Kommazahl so (bescheiden) abfrage ist der, weil die Funktion MOD jede Zahl als Ganzzahl interpretiert.
Das heisst, würde dort eine Kommazahl stehen, würde sie mit einer Ganzzahl rechnen. Deswegen schaue ich separat danach.

Ist es keine Kommazahl, wird geschaut, ob die Hochzahl ungerade ist (z.B. 3).
Eine ungerade Zahl ist jene, bei der MOD 2 nicht gleich 0 ist.
Ist eins von beiden der Fall, springe ich zu dem Abschnitt, wo ein negatives Ergebnis herauskommen muss.



Bei gerader Hochzahl ist das Ergebnis Positiv:
Code:
// Positives Ergebnis

      L     "Hochzahl"
      T     #Temp_Hochzahl

// Da das Ergebnis Positiv wird, kann das Vorzeichen der Basis zum Berechnen gedreht werden

      L     "Basis"
      L     -1.0
      *R
      T     #Temp_Basis

// Berechnen
      L     #Temp_Basis
      LN
      L     #Temp_Hochzahl

      *R

      EXP
      T     "Ergebnis"

      SPA   Ende

Ich drehe das Vorzeichen nur, weil die Funktion mit negativen Vorzeichen bei der Basis nicht rechnet. Aber da das Ergebnis sowieso positiv wird, macht das nichts.


Bei ungerader Hochzahl, wird das Ergebnis negativ
Code:
// Negatives Ergebnis
Neg:  NOP 0



      L     "Hochzahl"
      T     #Temp_Hochzahl

// Vorzeichen zum Berechnen drehen
      L     "Basis"
      L     -1.0
      *R
      T     #Temp_Basis

      L     #Temp_Basis
      LN
      L     #Temp_Hochzahl

      *R

      EXP
      T     #Temp_Ergebnis

// Vorzeichen drehen, damit das Ergebnis negativ ist
      L     -1.0
      *R

      T     "Ergebnis"

Ende: NOP 0

Hier drehe ich das Vorzeichen, damit berechnet werden kann. Danach Drehe ich das Vorzeichen einfach wieder.


Das ist jetzt nur gedacht für eine negative Basis mit einer positiven Hochzahl.

Bei positiver Hochzahl und Basis muss natürlich nichts gedreht werden etc. Das kann einfach so berechnet werden. Da kann alles übersprungen werden.

Die Kombinationen mit negativer Hochzahl habe ich noch nicht nachgeschaut.


Ist evtl. etwas umständlich, waren aber einfach so ein paar Zeilen schnell heruntergeschrieben.



Gruß

Chris
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nach den Potenzgesetzen bei rationalen Exponenten:
Zum Potenzieren einer negativen Zahl mit einem rationalen (gebrochenem) Exponent muß bei der gekürzten Bruchdarstellung des Exponenten der Nenner ungerade sein, weil man nicht eine gerade Wurzel aus einer negativen Zahl ziehen kann.

Beispiel:
Code:
(-2)^3.0  = -8       : 3.0 = 30/10 = 3/1  = Nenner ungerade
(-2)^3.1  geht nicht : 3.1 = 31/10        = Nenner gerade !
(-2)^3.2  = -9.189   : 3.2 = 32/10 = 16/5 = Nenner ungerade

Möglicherweise wird das Potenzieren von negativen Zahlen generell abgelehnt, weil die Genauigkeit von REAL-Zahlen nicht ausreicht zu entscheiden, ob der Nenner des Exponenten ungerade ist?

Harald
 
Also schaue ich erst mal, ob es sich um eine Kommazahl handelt. Der Grund, warum ich die Kommazahl so (bescheiden) abfrage ist der, weil die Funktion MOD jede Zahl als Ganzzahl interpretiert.
Das heisst, würde dort eine Kommazahl stehen, würde sie mit einer Ganzzahl rechnen. Deswegen schaue ich separat danach.
Hallo Chris,

irgendwie verstehe ich die Erklärung nicht, ich sehe den Zusammenhang zum MOD nicht, sie scheint nicht zum Code zu passen? Erstens ist durch das TRUNC vor dem MOD sichergestellt, daß vor dem MOD eine Ganzzahl ist. Und zweitens wird der ungewollte Code nach der Kommazahl-Prüfung trotzdem ausgeführt. Da sollte wohl besser mit "SPB Neg" weggesprungen werden (anstatt der O-Klammer).


Code:
// Überprüfen ob Hochzahl gerade oder ungerade ist

// Zahl mit Kommastelle
      O(
      L     "Hochzahl"
      TRUNC                   [COLOR="#0000FF"]// (nach TRUNC das Statusbit OV auswerten!)[/COLOR]
      [COLOR="#FF0000"]ITD                     // ITD gehört nicht hierher, muß weg[/COLOR]
      DTR
      L     "Hochzahl"
      [COLOR="#0000FF"]-R                      // ("-R" und "L 0.0" können beide entfallen)[/COLOR]
      [COLOR="#0000FF"]L     0.0[/COLOR]
      [COLOR="#FF0000"]<R                      // ändern zu "<>R"[/COLOR]
      )                       [COLOR="#0000FF"]// statt O-Klammer müßte eigentlich "SPB Neg"[/COLOR]

// Ungerade Zahl
      O(
      L     "Hochzahl"
      TRUNC
      L     2
      MOD
      [COLOR="#0000FF"]T     #Temp_Hochzahl    // (überflüssig)[/COLOR]
      L     0
      [COLOR="#FF0000"]>I                      // ändern zu "<>I"[/COLOR]
      )
      SPB   Neg
Statt "-R" und Vergleich der Differenz mit 0.0 kann auch gleich Vergleich "DTR(TRUNC(Hochzahl)) <> Hochzahl"

Wenn Du die 3 rot markierten Anweisungen änderst dann funktioniert Dein Code wahrscheinlich so wie Du wohl wolltest.
Ich meine aber, nach den Potenzgesetzen darf man die Vorzeichenproblematik nicht so einfach umgehen. Negative Zahlen können nicht mit jedem gebrochenen Exponent potenziert werden (siehe Beitrag #12), Du berechnest aber trotzdem ein Ergebnis, was in ca. 50% der Fälle nicht korrekt ist.

PS:
Code:
// anstatt
      MOD
      L     0
      <>I
      SPB   Neg

// geht auch
      MOD
      U     <>0
      SPB   Neg

// oder
      MOD
      SPN   Neg

Harald
 
Code:
// Überprüfen ob Hochzahl gerade oder ungerade ist

// Zahl mit Kommastelle
      O(
      L     "Hochzahl"
      TRUNC                   [COLOR=#0000FF]// (nach TRUNC das Statusbit OV auswerten!)[/COLOR]
      [COLOR=#FF0000]ITD                     // ITD gehört nicht hierher, muß weg[/COLOR]            // Ups :smile:. Hatte es aber bei mir nachträglich korrigiert.
      DTR                                                                     // War ich zu schnell mit dem Hochladen.
      L     "Hochzahl"
      [COLOR=#0000FF]-R                      // ("-R" und "L 0.0" können beide entfallen)[/COLOR]    // geht natürlich auch ohne
      [COLOR=#0000FF]L     0.0[/COLOR]
      [COLOR=#FF0000]<R                      // ändern zu "<>R"[/COLOR]
      )                       [COLOR=#0000FF]// statt O-Klammer müßte eigentlich "SPB Neg"[/COLOR]    // Hatte vorher hier auch SPB Neg. Mit beiden "Vergleichen".             
                                                                               // in je einem O() geht es aber auch. Oder es war Zufall

// Ungerade Zahl
      O(
      L     "Hochzahl"
      TRUNC
      L     2
      MOD
      [COLOR=#0000FF]T     #Temp_Hochzahl    // (überflüssig)[/COLOR]             // Stimmt
      L     0
      [COLOR=#FF0000]>I                      // ändern zu "<>I"[/COLOR]           // Kann es kleiner 0 werden?[COLOR=#FF0000][/COLOR]
      )
      SPB   Neg

Du hast natürlich recht mit deinen Kommentaren.

PN/DP schrieb:
Ich meine aber, nach den Potenzgesetzen darf man die Vorzeichenproblematik nicht so einfach umgehen. Negative Zahlen können nicht mit jedem gebrochenen Exponent potenziert werden (siehe Beitrag #12), Du berechnest aber trotzdem ein Ergebnis, was in ca. 50% der Fälle nicht korrekt ist.


Ich muss ehrlicherweise gestehen, ich habe mir die Potenzgesetze dazu nicht wirklich angesehen. Ich habe mich einfach nur an die Beispiele des TE gehalten. Dort fand ich es zwar auch komisch, dass z.B. (-2)^2.01 im Windows-Taschenrechner zur Ausgabe "Ungültige Eingabe" führte und nicht zu "+4,028", aber habe es "einfach mal rechnen lassen".




Gruß

Chris
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
      L     "Hochzahl"
      TRUNC
      L     2
      MOD
      [COLOR="#A9A9A9"]T     #Temp_Hochzahl    // (überflüssig)             // Stimmt[/COLOR]
      L     0
      [COLOR="#FF0000"]>I                      // ändern zu "<>I"[/COLOR]           // Kann es kleiner 0 werden?
Ja, das Ergebnis von "Ganzzahl MOD 2" kann 0, 1 oder -1 sein. Deshalb immer auf ==0 oder <>0 abfragen.
Code:
+ungerade MOD 2 = +1
  +gerade MOD 2 = 0
        0 MOD 2 = 0
  -gerade MOD 2 = 0
-ungerade MOD 2 = -1

Harald
 
Zurück
Oben