Array Inhalte miteinander Multiplizieren.
-
Es hapert daran, dass ich nicht weiß wie ich überhaupt damit anfangen soll, da ich noch nie Array Inhalte Multipliziert habe
-
@Timothy-Schanz sagte in Array Inhalte miteinander Multiplizieren.:
Es hapert daran, dass ich nicht weiß wie ich überhaupt damit anfangen soll, da ich noch nie Array Inhalte Multipliziert habe
Dann:
wie würdest du denn das Produkt17 * 35 * 2 * 19
von Hand berechnen? Richtig: erst 17*35. Ergebnis merken. Das Ergebnis dann *2 nehmen. Und das Ergebnis dann mal 19.Du musst eine Schleife schreiben. In einer Funktion.
Insgesamt sollten das circa 5 Zeilen Code sein inklusive Funktionskopf. Fang doch einfach an!
-
@Timothy-Schanz sagte in Array Inhalte miteinander Multiplizieren.:
Es hapert daran, dass ich nicht weiß wie ich überhaupt damit anfangen soll, da ich noch nie Array Inhalte Multipliziert habe
Kannst du denn die Summe über das Array bilden.
Oder den Mittelwert?
-
@wob sagte in Array Inhalte miteinander Multiplizieren.:
Insgesamt sollten das circa 5 Zeilen Code sein inklusive Funktionskopf.
float multiply(float *data, size_t length) { if (!data || !length) return 0; float result = data[0]; for (size_t i = 1; i < length; ++i) result *= data[i]; return result; }
Naja, da müsste man für 5 Zeilen schon ein bisschen sehr viel stopfen.
-
@Swordfish
Naja, super-viel stopfen muss man nicht:float mulall(float const* values, size_t n) { float accu = 1; for (size_t i = 0; i < n; i++) accu *= values[i]; return accu; }
Gut, zugegeben, die schliessende
}
in der selben Zeile mit demreturn
ist schräg.Alternativ:
float mulall(float const* values, size_t n) { float accu = 1; while (n--) accu *= *values++; return accu; }
Klar, wenn man sich die "unnötige" erste Multiplikation sparen will, wird's komplizierter. Aber das muss ja nicht sein.
Und wenn man unbedingt will könnte man es natürlich noch kürzer rekursiv machen:
float mulall(float const* values, size_t n) { return n ? values[0] * mulall(values + 1, n - 1) : 1; }
BTW: Ich denke es ist üblich das Produkt von null Zahlen als 1 zu definieren.
ps:
if (!data || !length)
Finde ich nicht gut. Damit maskierst du bloss Fehler (Aufruf mit
NULL
und Länge > 0).
-
@hustbaer sagte in Array Inhalte miteinander Multiplizieren.:
Finde ich nicht gut. Damit maskierst du bloss Fehler (Aufruf mit NULL und Länge > 0).
Dann brauchts mehr out-parameter.
-
@Swordfish sagte in Array Inhalte miteinander Multiplizieren.:
@hustbaer sagte in Array Inhalte miteinander Multiplizieren.:
Finde ich nicht gut. Damit maskierst du bloss Fehler (Aufruf mit NULL und Länge > 0).
Dann brauchts mehr out-parameter.
Oder „Garbage in, garbage out“
Die Parameter müssen halt gültig sein.
Man kann auch außerhalb testen, wenn es wichtig ist.
-
@DirkB Ich würde per assert die Gültigkeit der Parameter testen. Dann hat man was im Debug Modus und im Release ists dann halt tatsächlich GIGO.
-
Aber was ist denn ein "gültiger Parameter"? Insbesondere: ist Länge = 0 (mit pointer egal) gültig? Was erwartet man?
Wir haben eigentlich 4 Optionen:
a) UB - wir stellen uns auf den Standpunkt, dass die Funktion immer mit mindestens einenem Wert aufgerufen werden muss
b) 1 - 1 ist das neutrale Element der Multiplikation.
c) 0 - nichts geht rein, nichts kommt raus
d) Irgendein irgendwie geartetes Fehlerreporting
-
Wie wäre es mit dem float Wert NaN?
-
@wob sagte in Array Inhalte miteinander Multiplizieren.:
Aber was ist denn ein "gültiger Parameter"? Insbesondere: ist Länge = 0 (mit pointer egal) gültig? Was erwartet man?
Wir haben eigentlich 4 Optionen:
a) UB - wir stellen uns auf den Standpunkt, dass die Funktion immer mit mindestens einenem Wert aufgerufen werden muss
b) 1 - 1 ist das neutrale Element der Multiplikation.
c) 0 - nichts geht rein, nichts kommt raus
d) Irgendein irgendwie geartetes FehlerreportingAlso Länge größer 0 aber mit nullptr empfinde ich als ungültig. Wie auch immer man sich entscheidet, muss es halt dokumentiert werden.
-
@Tyrdal sagte in Array Inhalte miteinander Multiplizieren.:
Also Länge größer 0 aber mit nullptr empfinde ich als ungültig.
Ok, das ist klar! Aber das sollte UB sein. Das zu prüfen, sehe ich nicht als Aufgabe der Funktion.
NaN ist nur dann eine zusätzliche Möglichkeit, wenn ein float-Werte multipliziert werden sollen. Aber bei int? Und dann wäre es schön, wenn
multiply_array_int
undmultiply_array_float
sich gleich verhalten würden...
-
In C gibt es wohl noch keine Möglichkeit ein signaling NaN zu benutzen, dass würde eine Floating Point Exception der FPU auslösen.
#include <math.h> #include <stdlib.h> #include <stdio.h> float product(float *data, size_t length) { if (length == 0) return 1.0f; if (length >= 1 && !data) return NAN; float r = 1.0f; for (size_t i = 0; i < length; ++i) r *= data[i]; return r; } int main() { float p = 0.0f; float array[] = {1.0f, 2.0f, 3.0f, 4.0f}; p = product (array, sizeof(array)/sizeof(float)); printf("%f\n", p); p = product (NULL, 0); printf("%f\n", p); p = product (NULL, 2); printf("%f\n", p); }
-
@wob sagte in Array Inhalte miteinander Multiplizieren.:
NaN ist nur dann eine zusätzliche Möglichkeit, wenn ein float-Werte multipliziert werden sollen. Aber bei int? Und dann wäre es schön, wenn
multiply_array_int
undmultiply_array_float
sich gleich verhalten würden...Bei int kannst Du in C nicht viel machen, außer man gibt das Ergebnis als Parameter zurück und die Funktion hat als return Wert einen Fehlercode – Beispiel.
int multiply(int* result, int* input, size_t input_size);
-
@wob sagte in Array Inhalte miteinander Multiplizieren.:
Aber was ist denn ein "gültiger Parameter"? Insbesondere: ist Länge = 0 (mit pointer egal) gültig? Was erwartet man?
Wir haben eigentlich 4 Optionen:
a) UB - wir stellen uns auf den Standpunkt, dass die Funktion immer mit mindestens einenem Wert aufgerufen werden muss
b) 1 - 1 ist das neutrale Element der Multiplikation.
c) 0 - nichts geht rein, nichts kommt raus
d) Irgendein irgendwie geartetes FehlerreportingJe nach konkretem Anwendungsfall können die Antworten unterschiedlich aussehen. Wenn in der Anwendung Aufrufe mit
len == 0
einfach nicht vorkommen, macht es vermutlich Sinn (a) zu wählen. Evtl. auch noch (d), z.B. in Form von "write log message + abort()". Und wenn in der Anwendung Aufrufe mitlen == 0
möglich sind, kommt es halt drauf an in welchem Zusammenhang diese auftreten.Wenn man die Funktion als nicht-spezialisierte Hilfsfunktion für alle möglichen Anwendungen auslegen will, dann würde ich persönlich (b) wählen. U.a. weil man damit Aufrufe verketten kann, ala
mulall(arr1, len1) * mulall(arr2, len2)
, ohne sich Gedanken machen zu müssen wie die einzelnen Werte aufarr1
undarr2
verteilt sind. Ich könnte mir vorstellen dass das in manchen Fällen praktisch ist.
-
@Swordfish sagte in Array Inhalte miteinander Multiplizieren.:
@hustbaer sagte in Array Inhalte miteinander Multiplizieren.:
Finde ich nicht gut. Damit maskierst du bloss Fehler (Aufruf mit NULL und Länge > 0).
Dann brauchts mehr out-parameter.
Ich wüsste nicht wozu.
-
@hustbaer Wenn zwischen verschiedenartigen fehlerhaften Parametern unterscheiden können möchte. Aber nachdem ich die Diskussion die auf meinen Beitrag hin entstanden ist gelesen habe bin ich auch für GIGO.
-
@hustbaer sagte in Array Inhalte miteinander Multiplizieren.:
@wob sagte in Array Inhalte miteinander Multiplizieren.:
Aber was ist denn ein "gültiger Parameter"? Insbesondere: ist Länge = 0 (mit pointer egal) gültig? Was erwartet man?
Ein mathematisches Produkt ist als 1 definiert, wenn es leer ist z.B. .
-
@wob sagte in Array Inhalte miteinander Multiplizieren.:
@Tyrdal sagte in Array Inhalte miteinander Multiplizieren.:
Also Länge größer 0 aber mit nullptr empfinde ich als ungültig.
Ok, das ist klar! Aber das sollte UB sein.
Also gerade das häufige UB macht C++ ja so unhandlichund unsicher. Ich weiß nicht ob man da selber noch mit dazu beitragen sollte.
-
@Tyrdal sagte in Array Inhalte miteinander Multiplizieren.:
@wob sagte in Array Inhalte miteinander Multiplizieren.:
@Tyrdal sagte in Array Inhalte miteinander Multiplizieren.:
Also Länge größer 0 aber mit nullptr empfinde ich als ungültig.
Ok, das ist klar! Aber das sollte UB sein.
Also gerade das häufige UB macht C++ ja so unhandlichund unsicher. Ich weiß nicht ob man da selber noch mit dazu beitragen sollte.
Sorge beim Aufruf dafür, dass es kein UB gibt.
Evtl. mit einer eigenen Funktion product_s()