Discussion:
Prozentrechnung mit angezeigter Rundung
(zu alt für eine Antwort)
Michael Happ
2009-11-26 11:43:06 UTC
Permalink
Hallo Gemeinde,

folgendes Problem:

115 17,16%
222 33,13%
333 49,70%

670 100,00%

Die Prozentzahlen in der ersten drei Zeilen geben den jeweiligen
Anteil zur Summe wieder, natürlich entsprechend gerundet. In der
letzten Zeile steht die Summe der jeweiligen Spalte.

Wie löst man dieses "Anzeigeproblem", so dass ein händisches
Aufsummieren der angezeigten Werte dann auch 100% ergibt?

Gruß Micha
Andreas Killer
2009-11-26 11:53:38 UTC
Permalink
Post by Michael Happ
Die Prozentzahlen in der ersten drei Zeilen geben den jeweiligen
Anteil zur Summe wieder, natürlich entsprechend gerundet. In der
letzten Zeile steht die Summe der jeweiligen Spalte.
Wie löst man dieses "Anzeigeproblem", so dass ein händisches
Aufsummieren der angezeigten Werte dann auch 100% ergibt?
In dem man nicht rundet sondern die Zellen der Prozentzahlen mit
Prozent und 2 Nachkommastellen formatiert.

Dann gibt auch die Summe der Prozentzahlen 100,00%

Andreas.
Alexander Wolff
2009-11-26 12:16:25 UTC
Permalink
Post by Andreas Killer
Post by Michael Happ
Die Prozentzahlen in der ersten drei Zeilen geben den jeweiligen
Anteil zur Summe wieder, natürlich entsprechend gerundet. In der
letzten Zeile steht die Summe der jeweiligen Spalte.
Wie löst man dieses "Anzeigeproblem", so dass ein händisches
Aufsummieren der angezeigten Werte dann auch 100% ergibt?
In dem man nicht rundet sondern die Zellen der Prozentzahlen mit
Prozent und 2 Nachkommastellen formatiert.
Dann gibt auch die Summe der Prozentzahlen 100,00%
Das löst das Problem nicht. http://excelformeln.de/formeln.html?welcher=347
--
Moin+Gruss Alexander - MVP for MS Excel - www.xxcl.de - mso2000sp3 --7-2
Andreas Killer
2009-11-26 12:35:32 UTC
Permalink
Post by Alexander Wolff
Das löst das Problem nicht. http://excelformeln.de/formeln.html?welcher=347
Das sehe ich anders, die Werte vom OP bzw. Formeln wie folgt:

A1 115
A2 222
A3 333
A4
A5 =SUMME(A1:A3)
B1 =A1/A$5
B2 =A2/A$5
B3 =A3/A$5
B4
B5 =SUMME(B1:B3)

Ergibt bei mir in A5 670 und in B5 1 oder 100%, wenn man die Zelle
entsprechend formatiert. Bei Dir nicht?

Andreas.
Thomas Kühn
2009-11-26 14:55:04 UTC
Permalink
Moin,
Post by Andreas Killer
A1 115
A2 222
A3 333
A4
A5 =SUMME(A1:A3)
B1 =A1/A$5
B2 =A2/A$5
B3 =A3/A$5
B4
B5 =SUMME(B1:B3)
Hier wird sowohl richtig gerechnet als auch angezeigt.
Post by Andreas Killer
Ergibt bei mir in A5 670 und in B5 1 oder 100%, wenn man die Zelle
entsprechend formatiert. Bei Dir nicht?
Bei mir ebenfalls. Trotzdem ist das was angezeigt wird
zusammen nur 99,99%. Setzt mal auf drei Stellen hinter
dem Komma, dann sind es 99,999% und erst bei 4 Stellen
sind es genau 100. Das Problem ist in diesem Fall
dass die gerundete Anzeige stimmt.

Bei 2 Stellen:
115 17,16%
222 33,13%
333 49,70%
670 100,00%

Bei 3 Stellen:
115 17,164%
222 33,134%
333 49,701%
670 100,000%

Bei 4 Stellen:
115 17,1642%
222 33,1343%
333 49,7015%
670 100,0000%


Also entweder mehr Stellen anzeigen oder damit leben.



Gruß Thomas

--

http://www.thomas-kuehn.de
Michael Happ
2009-11-26 13:18:47 UTC
Permalink
Hallo Andreas,
Das sehe ich anders ...
Alexander hat Recht!
Es geht darum, dass die *angezeigten* Werte (nicht die tatsächlichen,
mit entsprechend vielen Nachkommastellen) aufaddiert nicht 100%
ergeben, sondern halt 99,99%.

@Alexander
Hmmm. Recht aufwändig .... Gibt es vielleicht noch andere Workarounds?
Auf jeden Fall: Vielen Dank für den Link!

Micha
Andreas Killer
2009-11-26 17:22:05 UTC
Permalink
Post by Michael Happ
Alexander hat Recht!
Es geht darum, dass die *angezeigten* Werte (nicht die tatsächlichen,
mit entsprechend vielen Nachkommastellen) aufaddiert nicht 100%
ergeben, sondern halt 99,99%.
Hmmm. Recht aufwändig .... Gibt es vielleicht noch andere Workarounds?
Ja, einen ganz einfachen:

Dieses Problem ist keines, sondern besteht nur im Kopf, eine typische
visuelle Fehlleistung. Ich weiß, erschlagt mich nicht gleich. :-))

Die Fragen sind doch diese:

a.) Welchen der einzelnen Prozentwerte man gerne verfälschen möchte um
visuell auf 100% zu kommen.
b.) Ist das dann dieser Prozentwert noch richtig?

Ich sage nein, aber man kann Excel auch so rechnen lassen:

Setzte unter Optionen einen Haken bei Iteration und die maximale
Iterationzahl auf 1.

Formeln und Werte wie folgt:

A1 115
A2 222
A3 333
A5 =SUMME(A1:A3)
B1 =RUNDEN(A1/A$5;4)
B2 =RUNDEN(A2/A$5;4)
B3 =RUNDEN(A3/A$5;4)+1-B5
B5 =SUMME(B1:B3)

Nun gibt es visuell und rechnerisch 100%tig 100 Prozent. Wenn nicht,
dann einfach nochmal F9 drücken. ;-)

Andreas.
Andreas Killer
2009-11-27 07:03:29 UTC
Permalink
Post by Michael Happ
Hmmm. Recht aufwändig .... Gibt es vielleicht noch andere Workarounds?
Ich hätte da noch ein Möglichkeit, mit einer UDF.

A1 115
A2 222
A3 333
A5 =SUMME(A1:A3)
B1 =A1/A$5
B2 =A2/A$5
B3 =A3/A$5
B5 =SUMME(B1:B3)
C1:C3 {=RundenZuSumme(1;4;$B1:$B3)}
C5 =SUMME(C1:C3)

Mit der UDF läßt sich auch das Beispiel auf
http://excelformeln.de/formeln.html?welcher=347
nachrechnen, macht ja auch ziemlich das gleiche.

Ist wahrscheinlich längst nicht so schnell wie die Formeln, dafür aber
benutzerfreundlicher bei der Anpassung.

Allerdings denke ich das dieses Verfahren einen Pferdefuß hat, denn
die Verteilung ist krumm. Wenn man sich

A1 1,1
A2 2,2
A3 3,3
A4 4,4
A5 =SUMME(A1:A4)
B1:B4 {=RundenZuSumme(10;0;A1:A4)}
B5 =SUMME(B1:B4)

anschaut, dann würde ich in B1 bis B4 die Werte von 1 bis 4 erwarten...

Andreas.

Function RundenZuSumme(ByVal Soll As Double, ByVal Stellen As _
Integer, Bereich As Range) As Variant
'Rundet alle Werte in Bereich auf Anzahl Stellen, _
modifiziert die Einzelwerte damit diese als Summe Soll _
ergeben, gibt alle Werte als Matrix zurück
Dim Res(), X As Long, Y As Long, mX As Long, mY As Long
Dim Max As Double, Temp As Double, Summe As Double

'Werte einlesen
Res = Bereich
'Die tatsächliche Summe berechnen
For Y = LBound(Res) To UBound(Res)
For X = LBound(Res, 2) To UBound(Res, 2)
Summe = Summe + Res(Y, X)
Next
Next

'Verteilung der Einzelwerte zum Erreichen des Soll berechnen
Summe = (Summe - Soll) / ((UBound(Res) - LBound(Res) + 1) * ( _
UBound(Res, 2) - LBound(Res, 2) + 1))

'Werte runden
For Y = LBound(Res) To UBound(Res)
For X = LBound(Res, 2) To UBound(Res, 2)
'Verteilung aufaddieren
Res(Y, X) = Res(Y, X) + Summe
'Wert runden
Temp = WorksheetFunction.Round(Res(Y, X), Stellen)
'Die Position des Ausgleichwertes bestimmen
If Max = Empty Then
Max = Res(Y, X) - Temp
mY = Y
mX = X
Else
If Res(Y, X) - Temp > Max Then
Max = Res(Y, X) - Temp
mY = Y
mX = X
End If
End If
'Gerundeten Wert speichern
Res(Y, X) = Temp
'Vom Soll abziehen
Soll = Soll - Temp
Next
Next

'Den Ausgleichwert korrigieren
Res(mY, mX) = Res(mY, mX) + Soll
'Werte zurückgeben
RundenZuSumme = Res
End Function
Bernd P
2009-11-28 17:20:20 UTC
Permalink
Hallo Andreas,

Deine Funktion ist leider nicht korrekt.

Falls Du die Beispielzahlen von http://excelformeln.de/formeln.html?welcher=347
durch 1000 teilst und dann auf 0 Stellen rundest, kommen bei Deiner
Funktion Ausgabewerte heraus, die von denen der genannten Seite zu
sehr abweichen, Deine:
5
0
-79
-14
66
130
16
547
2
-1
7
3
Aber korrekt wäre:
5
0
-79
-15
66
129
16
549
2
-1
7
3

Viele Grüße,
Bernd
Andreas Killer
2009-11-30 08:36:35 UTC
Permalink
Post by Bernd P
Deine Funktion ist leider nicht korrekt.
Naja, ich sag mal ja und nein. :-)
Post by Bernd P
Falls Du die Beispielzahlen von http://excelformeln.de/formeln.html?welcher=347
durch 1000 teilst und dann auf 0 Stellen rundest, kommen bei Deiner
Funktion Ausgabewerte heraus, die von denen der genannten Seite zu
Das ist richtig und das muss auch so sein, soweit ich das durchblicke.

Ich bin ja kein Formel-Experte und daher auch nicht so ganz sicher,
aber ich denke das diese Formel 347 gar nicht auf das Prozent-Problem
angewendet werden kann.

Ich hatte zuerst versucht die Excelformel per VBA nachzubilden und bin
dann auf eine Routine gekommen, die ich am 27.11. gepostet hatte.

Das geht dann auch soweit, funktioniert aber nur bei bestimmten
Konstellationen wo die Summe geringfügig vom Soll abweicht.

Mein Problemfall:

Wenn ich
1,1
2,2
3,3
4,4
summiere, kommt da 11 raus. Nun möchte ich gerne aber gerundet 10
rausbekommen.

Ich habe mich dann mit der Formel rumgeplagt, aber es nicht
hinbekommen das ich auf die Einzelwerte
1
2
3
4
komme. Mit meinem VBA-Code ging das ebenso wenig.

Auch der andere Fall das ich auf
2
3
4
5
komme, d.h. zur Summe 14 runden möchte ging nicht.

Es hat dann einige Zeit gedauert bis mir dann endlich klar wurde das
die Routine (die Formel auch ?) jeden Wert nur möglichst minimal um
eine immer gleiche Größe ändert um zum Ergebnis zu kommen. Ich nenne
das mal die absolute Methode.

Und da liegt das Dilemma bei größeren Abweichungen zum Soll.

Wenn ich das auf ein prozentuales Problem anwende, dann stimmen
plötzlich die Abweichungen nicht mehr und kommen in Schieflage, weil
ich dann am Ende einen Einzelwert "brutal" in eine Richtung
korrigieren muss. Auch eine mehrfache Schleife bringt da keine Abhilfe.

Daher habe ich es mit einer prozentualen Verschiebung versucht und
diese bringt für die Fälle des OP und meines ein 1a Ergebnis.

Das Ergebnis zur der Formel 347 muss logischer Weise abweichen, da
prozentual die größeren Werte mehr korrigiert werden als die kleineren.

Ich denke das sich hier die Wege trennen und keine Balance zwischen
der prozentualen und der absoluten Methode finden läßt, oder?

Andreas.
Bernd P
2009-12-01 12:08:45 UTC
Permalink
Hallo Andreas,

Ich kann Dir leider nicht zustimmen.

Gib Deine Werte 1,1; 2,2; 3,3; 4,4 in die Zellen K1:K4 ein und dann z.
B. in L1:L4 als Matrixformel:
=dHondt(10,K1:K4)

Dann bekommst Du Deine gewünschte Lösung.

Die Webseite http://excelformeln.de/formeln.html?welcher=347 zeigt ein
Beispiel, welches dort auch korrekt gelöst wird. Meines Erachtens aber
nicht auf eine korrekte Art und Weise. Falls ich die Zeit finde,
stelle ich ene IMHO bessere (und korrekte) Vorgehensweise vor.

Meine Funktion dHondt ist für diese Art Aufgaben zwar grundsätzlich
geeignet, aber zugegebenermaßen nicht ideal.

Viele Grüße,
Bernd
Andreas Killer
2009-12-02 09:40:09 UTC
Permalink
Post by Bernd P
Ich kann Dir leider nicht zustimmen.
Gib Deine Werte 1,1; 2,2; 3,3; 4,4 in die Zellen K1:K4 ein und dann z.
=dHondt(10,K1:K4)
Dann bekommst Du Deine gewünschte Lösung.
Das ist schon richtig, aber wenn die Abweichung größer wird, dann
passt es nicht mehr: =dHondt(14,K1:K4) gibt 1;3;4;6 und nicht 2;3;4;5

Und bei negativen Zahlen -1,1;-2,2;-3,3;-4,4 versagt dHondt komplett
und gibt 0;0;0;0 zurück.
Post by Bernd P
Die Webseite http://excelformeln.de/formeln.html?welcher=347 zeigt ein
Beispiel, welches dort auch korrekt gelöst wird. Meines Erachtens aber
nicht auf eine korrekte Art und Weise. Falls ich die Zeit finde,
Das denke ich auch!
Post by Bernd P
Meine Funktion dHondt ist für diese Art Aufgaben zwar grundsätzlich
geeignet, aber zugegebenermaßen nicht ideal.
Trifft auf die eigentlich auch die Aussage:

D’Hondt erfüllt die Mehrheitsbedingung, nicht aber die
Minderheitsbedingung. D. h. eine Partei, die mindestens 50 % der
Stimmen auf sich vereinigt, erhält auch mindestens 50% der Sitze.
Umgekehrt kann aber eine Partei, die nicht mindestens 50 % der Stimmen
auf sich vereinigt, trotzdem 50 % der Sitze erhalten, wenn alle
anderen Parteien ein schlechteres Stimmenergebnis haben. Die Erfüllung
der Mehrheitsbedingung wird durch die systematische Bevorzugung
größerer Parteien „erkauft“.

auf Wikipedia (http://tinyurl.com/y9yexpa) zu?

Andreas.
Bernd P
2009-12-02 11:27:50 UTC
Permalink
Hallo Andreas,

Sortiere wie gesagt die Eingabedaten vorher nach dem Rundungsfehler.

Für negative Zahlen muss man eben (leider) erst von allen Zahlen ihr
Minimum subtrahieren und es später wieder auf die Lösung addieren.
Aber das Verfahren ist nicht ideal.

Klar, die Verletzung der Minderheitsbedingung ist bei meiner
Implementierung auch gegeben.

Viele Grüße,
Bernd
Bernd P
2009-12-03 22:45:15 UTC
Permalink
Hallo,

Nachtrag: Ein allgemeiner Ansatz sowohl für absolute als auch relative
(Prozent-) Zahlen:
http://sulprobil.com/html/largest_remainder.html

Viele Grüße,
Bernd
Alexander Wolff
2009-12-04 15:50:40 UTC
Permalink
Post by Bernd P
Hallo,
Nachtrag: Ein allgemeiner Ansatz sowohl für absolute als auch relative
http://sulprobil.com/html/largest_remainder.html
Bei Feststellungs-Steuererklärungen, wo centgenau Abschlagsteuern
aufzuteilen sind, jedoch zusätzlich dieses auf die einzelnen Beteiligten
aufgeteilt werden muss, runde ich nach einem manuellen Muster:

[1] Abschlagsteuer, z.B. SolZ centgenau

[2] Aufteilung nach Schlüssel auf Beteiligte mit =RUNDEN(...;2)

[3] "Diff" ist eine Tabelle mit Nullwerten und Summen in der gleichen Größe
wie [2].

[4] Summe [2] + [3] ergibt dann wieder [1], wenn [3] richtig gefüllt.

Vorteil eines derart manuellen Vorgangs: Man kann auch MEHRERE Beteiligte
anders runden. Außerdem kann man bei einer hier nachteiligen
Berücksichtigung eines Beteiligten bei erneutem Rundungsbedarf für ihn
positiv korrigieren.
--
Moin+Gruss Alexander - MVP for MS Excel - www.xxcl.de - mso2000sp3 --7-2
Bernd P
2009-12-05 11:46:24 UTC
Permalink
Hallo Alexander,

Kannst Du bitte ein Beispiel für die "nachteilige Berücksichtigung
eines Beteiligten" bei meinem Vorgehen
http://sulprobil.com/html/largest_remainder.html
geben?

Oder ist es nicht vielmehr so, dass ich Dir und einigen Steuerberatern
und Steuerbeamten gerade etwas Arbeit erleichtert habe? :-)

Viele Grüße,
Bernd
Alexander Wolff
2009-12-09 16:24:25 UTC
Permalink
Post by Bernd P
Hallo Alexander,
Kannst Du bitte ein Beispiel für die "nachteilige Berücksichtigung
eines Beteiligten" bei meinem Vorgehen
http://sulprobil.com/html/largest_remainder.html
geben?
Oder ist es nicht vielmehr so, dass ich Dir und einigen Steuerberatern
und Steuerbeamten gerade etwas Arbeit erleichtert habe? :-)
Wer weiß. Vielleicht spiele ich ja mal damit herum (hab kein 2007
installiert und öffne daher Dein Beispiel noch nicht).

Nein, meine manuellen Rundungen haben schon etwas für sich:

Angenommen, es gibt (a) 5 Beteiligte mit 10% und (b) 2 mit 25%, zusammen
100%. Nun kann man bei einer Summenverfehlung von +1 Einheit bei (a) je -1
und bei (b) je +2 berücksichtigen (-1 = 5*-1 + 2*+1). Damit - was allerdings
nicht immer funktioniert; ideal ist dafür eine gerade und eine ungerade
Anzahl von gleich Beteiligten in einer Aufteilung - korrigiert man nicht nur
die Rundung selbst, sondern tut es für die jeweils gleich Beteiligten auch
noch in gleicher Weise (verlangt niemand).

Mit ein bißchen Übung kann man dies dann auch in größeren Zusammenhängen
perfektionieren. Praktische Bedeutung: nahe Null. Aber das Finanzamt braucht
es bei Abzugssteuern halt centgenau.
--
Moin+Gruss Alexander - MVP for MS Excel - www.xxcl.de - mso2000sp3 --7-2
Bernd P
2009-12-09 18:19:25 UTC
Permalink
Hallo Alexander,
...
...
Na, da bin ich anderer Ansicht. "Manuelle Rundungen" sind hier wohl
eher diskretionäre Zuteilungen. Minimale Fehler kann man automatisch
ermitteln. Auch centgenau.

Viele Grüße,
Bernd
Andreas Killer
2009-12-08 11:31:33 UTC
Permalink
Post by Bernd P
Nachtrag: Ein allgemeiner Ansatz sowohl für absolute als auch relative
(Prozent-) Zahlen:http://sulprobil.com/html/largest_remainder.html
Der Ansatz ist sehr gut, vor allen Dingen die Idee mit dem RankOfError
bei den Formeln!

Zur Funktion der Formeln kann ich nicht so viel sagen, die VBA-Routine
funktioniert jedoch nicht wenn die Summe aller Zahlen 0 ist.

Außerdem kann man sie nicht aus VBA heraus mit "V = LRM("A", -3, Range
("A1:A12"))" aufrufen, gibt einen RTE 424, weil Application.Caller
"Fehler 2023" ist.

Rufe ich sie mit einem Array(1 to 12) auf gibt es einen RTE 9 während
der Verarbeitung.

Aber der RankOfError hat mich auf eine Idee gebracht und die löst
viele Probleme. Nun habe ich eine Routine die alle (?) Fälle berechnen
kann und mit der man auch gerne mal 200% geben kann.

Aber rechnet sie tatsächlich immer richtig?

Andreas.

Function RundenZuSumme(Bereich As Variant, Stellen As Integer, _
Optional Soll, Optional Prozentual) As Variant
'Rundet alle Werte in Bereich auf Anzahl Stellen, _
modifiziert die Einzelwerte (prozentual) damit diese als _
Summe Soll ergeben, gibt alle Werte als Matrix zurück
Dim Result(), X As Long, Y As Long
Dim RankOfError(), i As Long, j As Long, k As Long
Dim Steps As Long, Diff, Rest, Summe, Temp

'Wenn kein Soll, dann gerundete Summe annehmen
If IsMissing(Soll) Then
With WorksheetFunction
Soll = .Round(.Sum(Bereich), Stellen)
End With
End If
Rest = Soll

'Prozentuale Verschiebung
If IsMissing(Prozentual) Then
Prozentual = False
Else
Prozentual = CBool(Prozentual)
End If
If Prozentual Then
Summe = WorksheetFunction.Sum(Bereich)
If Summe = 0 Or Soll = 0 Then Diff = 10 ^ -(Stellen - 1) _
Else Diff = 0
Diff = (Soll + Diff) / (Summe + Diff)
End If

If TypeOf Bereich Is Range Then
'Werte einlesen
With WorksheetFunction
Result = .Transpose(.Transpose(Bereich))
End With
ElseIf IsArray(Bereich) Then
'Sicherstellen das wir ein 2D-Array haben
Result = WorksheetFunction.Transpose(Bereich)
Else
'Damit kann ich nix anfangen
RundenZuSumme = Bereich
Exit Function
End If

'Korrekturwerte initialisieren
ReDim RankOfError(1 To 3, 1 To (UBound(Result) - LBound( _
Result) + 1) * (UBound(Result, 2) - LBound(Result, 2) + 1))

'Werte runden
For Y = LBound(Result) To UBound(Result)
For X = LBound(Result, 2) To UBound(Result, 2)
'Wert runden
If Prozentual Then
Temp = WorksheetFunction.Round(Result(Y, X) * Diff, _
Stellen)
Else
Temp = WorksheetFunction.Round(Result(Y, X), Stellen)
End If
i = i + 1
'Abweichung berechnen
RankOfError(1, i) = Abs(Result(Y, X) - Temp)
'Position speichern
RankOfError(2, i) = Y
RankOfError(3, i) = X
'Gerundeten Wert speichern
Result(Y, X) = Temp
'Vom Soll abziehen
Rest = Rest - Temp
Next
Next

'RankOfError sortieren
For i = LBound(RankOfError, 2) To UBound(RankOfError, 2) - 1
For j = i + 1 To UBound(RankOfError, 2)
If RankOfError(1, i) < RankOfError(1, j) Then
For k = LBound(RankOfError) To UBound(RankOfError)
Temp = RankOfError(k, i)
RankOfError(k, i) = RankOfError(k, j)
RankOfError(k, j) = Temp
Next
End If
Next
Next

'Anzahl Schritte
Steps = (Abs(Rest) / (10 ^ -Stellen))

'Speedup für große Abweichungen
If Steps > UBound(RankOfError, 2) Then
'Korrekturwert pro Schritt
Diff = (10 ^ -Stellen) * Sgn(Rest) * (Steps \ UBound( _
RankOfError, 2))
'Einmal alle Werte
For i = LBound(RankOfError, 2) To UBound(RankOfError, 2)
Result(RankOfError(2, i), RankOfError(3, i)) = Result( _
RankOfError(2, i), RankOfError(3, i)) + Diff
Next
'Restliche Schritte berechnen
Steps = Steps - (Steps \ UBound(RankOfError, 2)) * UBound( _
RankOfError, 2)
End If

'Korrekturwert pro Schritt
Diff = (10 ^ -Stellen) * Sgn(Rest)
'Die Ausgleichwerte korrigieren
j = LBound(RankOfError, 2) - 1
For i = 1 To Steps
j = j + 1
Result(RankOfError(2, j), RankOfError(3, j)) = Result( _
RankOfError(2, j), RankOfError(3, j)) + Diff
Next

If TypeOf Bereich Is Range Then
'Werte zurückgeben
RundenZuSumme = Result
Else
'Array zurückgeben
RundenZuSumme = WorksheetFunction.Transpose(Result)
End If
End Function
Bernd P
2009-12-08 12:25:28 UTC
Permalink
Hallo Andreas,

Danke für Deine Hinweise.

Die Prüfung auf pathologische Eingabewerte und den Aufruf über VBA
realisiere ich vielleicht später, wenn ich die Zeit und Lust darauf
verspüre.

Ein kleiner Hinweis: IMHO liefert Dein VBA Makro keine 200%, sondern
0%: Es rechnet nicht richtig. Runde im 1. Beispiel auf meiner Seite
http://sulprobil.com/html/largest_remainder.html auf -2 Stellen und
vergleiche unsere Ergebnisse...

Viele Grüße,
Bernd
Andreas Killer
2009-12-08 14:07:38 UTC
Permalink
Post by Bernd P
Ein kleiner Hinweis: IMHO liefert Dein VBA Makro keine 200%, sondern
0%: Es rechnet nicht richtig. Runde im 1. Beispiel auf meiner Seite
http://sulprobil.com/html/largest_remainder.html auf -2 Stellen und
vergleiche unsere Ergebnisse...
Du meinst die Werte

A1 4523
A2 456
A3 -78845
A4 -14491
A5 65789
A6 129512
A7 15562
A8 548555
A9 1590
A10 -897
A11 6968
A12 2987

und die Formel
G1:G12 {=LRM("A";-2;A1:A12)/1000}
?

Da sehe ich keinen Unterschied zu der Formel
F1:F12 {=RundenZuSumme(A1:A12;-2)/1000}

Beide liefern

4,5
0,5
-78,9
-14,5
65,8
129,5
15,6
548,5
1,6
-0,9
7
3

Und die Summe 681,7 ist doch auch richtig, oder nicht?

Da ist bei mir kein Unterschied zu sehen, bei Dir schon?

Andreas.
Andreas Killer
2009-12-08 15:06:59 UTC
Permalink
Post by Bernd P
0%: Es rechnet nicht richtig. Runde im 1. Beispiel auf meiner Seite
http://sulprobil.com/html/largest_remainder.html auf -2 Stellen und
vergleiche unsere Ergebnisse...
Ich hab doch einen Unterschied festgestellt, beim Runden auf -4 Stellen.

Dort ergibt

Wert; RundenZuSumme; LRM
4523; -10000 ; 0
-14491; -10000 ; -20000

restliche Wert sind gleich. Wieso korrigiert Deine Berechnung hier
nicht den Wert 4523?

Ich mache das weil ja der Fehler dieses Wertes zum gerundeten Wert
größer ist:

RUNDEN(4523;-4) = 0 = Differenz 4523
RUNDEN(-14491;-4) = -10000 = Differenz 4491

Und der größte (absolute) Fehler muss doch korrigiert werden, oder?

Andreas.
Bernd P
2009-12-08 20:39:01 UTC
Permalink
Hallo Andreas,
Post by Andreas Killer
...
Und der größte (absolute) Fehler muss doch korrigiert werden, oder?
...
Oder. Die auf 10.000 gerundete Summe ist hier 680.000 (da wollen wir
also hin), aber die Summe der auf 10.000 gerundeten Summanden beträgt
690.000 (das ist 10.000 zuviel).

Wir müssen also einem der Summanden 10.000 abknöpfen. Welchem? Doch
sicherlich demjenigen, der nach Einzelrundung den POSITIV größten
Fehler aufweist (NICHT: den betragsmäßig größten Fehler).

Du ziehst die 10.000 von -4.523 ab, was auf einen absolut größten
Fehler von -14.523 (anfangs +4,523, am Ende -10.000!!) hinausläuft.
Ich ziehe die 10.000 von +4.491 ab und komme damit auf einen absolut
größten Fehler von 5.509 (anfangs -14.491, am Ende -20.000).

Viele Grüße,
Bernd
Andreas Killer
2009-12-09 08:03:47 UTC
Permalink
Post by Bernd P
Wir müssen also einem der Summanden 10.000 abknöpfen. Welchem? Doch
sicherlich demjenigen, der nach Einzelrundung den POSITIV größten
Fehler aufweist (NICHT: den betragsmäßig größten Fehler).
Wieso muss das so sein? Verstehe ich nicht.

Andreas.
Bernd P
2009-12-09 08:27:57 UTC
Permalink
Hallo Andreas,

Du willst doch dass das Endergebnis gerundet ist, aber möglichst wenig
vom Anfangsbestand abweicht.

Schau Dir doch bitte die Differenzen zwischen Deinen einzelnen Zahlen
(vorher und nachher) einmal an und vergleiche das mit meinen.

Deine größte vorkommende Differenz ist größer ist als meine, also
läufts net rund in Deinem Programm...

Hier noch ein einfaches Beispiel:
1.6
-1.1
-1.2
Zu runden auf 0 Stellen (absolut).
Die Lösung:
1
-1
-1
(maximaler Fehler: 0.6, die Differenz zwischen vorher und nachher bei
der ersten Zahl)
Deine falsche Lösung:
2
-1
-2
(maximaler Fehler: 0.8, siehe letzte Zahl)

Viele Grüße,
Bernd
Andreas Killer
2009-12-09 11:32:55 UTC
Permalink
Post by Bernd P
Du willst doch dass das Endergebnis gerundet ist, aber möglichst wenig
vom Anfangsbestand abweicht.
Hmm, will ich das... muss ich das wollen?
Post by Bernd P
1.6
-1.1
-1.2
Zu runden auf 0 Stellen (absolut).
1
-1
-1
Ja ist korrekt, sehe ich auch so.
Post by Bernd P
2
-1
-2
Hää??????

Halt stop, nimm mal einfach

A1 1,6
A2 -1,1
A3 -1,2
B1:B3 {=RundenZuSumme(A1:A3;0)}

dann kommt da auch die richtige Lösung raus, der Trick bei der
prozentualen Verschiebung ala
B1:B3 {=RundenZuSumme(A1:A3;0;;1)}
(wobei die falsche Lösung rauskommt) ist ein anderer, das
Prozentbeispiel machts deutlich:

A1 115
A2 222
A3 333
A4 =SUMME(A1:A3)
B1 =A1/A$4
B2 =A2/A$4
B3 =A3/A$4
B4 =SUMME(B1:B3)
C1:C3 {=RundenZuSumme(B1:B3;4;2;1)}
C4 =SUMME(C1:C3)

In B4 steht ja 100%, nun möchte ich aber die Einzelwerte so runden das
da 200% rauskommt.
Somit stehen in C1 bis C3 die doppelten Werte von B1 bis B3:
34,33%
66,27%
99,40%

rechne ich das ohne prozentuale Verschiebung kommt da
50,50%
66,47%
83,03%

raus, was "Blödsinn" ist.

Aber die Sache mit der geringsten Abweichung muss ich mir nochmal
durch den Kopf gehen lassen.

Andreas.
Bernd P
2009-12-09 23:11:38 UTC
Permalink
Hallo Andreas,
Post by Andreas Killer
...
Post by Bernd P
Du willst doch dass das Endergebnis gerundet ist, aber möglichst wenig
vom Anfangsbestand abweicht.
Hmm, will ich das... muss ich das wollen?
...
Nein, das musst Du nicht.

Wir haben offensichtlich unterschiedliche Qualitätsansprüche.

Gruß,
Bernd
Andreas Killer
2009-12-10 08:08:42 UTC
Permalink
Post by Bernd P
Post by Andreas Killer
Post by Bernd P
Du willst doch dass das Endergebnis gerundet ist, aber möglichst wenig
vom Anfangsbestand abweicht.
Hmm, will ich das... muss ich das wollen?
Nein, das musst Du nicht.
Wir haben offensichtlich unterschiedliche Qualitätsansprüche.
Nönö, offenbar nicht, denn Du hast völlig recht.

Soweit ist der Groschen bei mir schon mal gefallen, nur die Lösung in
meiner Routine entzieht sich mir noch, naja, wird schon noch werden.

Wenn man jemanden hat der es richtig vormacht, sollte das nachmachen
ja irgendwann klappen. :-))

Andreas.
Andreas Killer
2009-12-11 13:54:06 UTC
Permalink
Post by Bernd P
Du ziehst die 10.000 von -4.523 ab, was auf einen absolut größten
Fehler von -14.523 (anfangs +4,523, am Ende -10.000!!) hinausläuft.
Ich ziehe die 10.000 von +4.491 ab und komme damit auf einen absolut
größten Fehler von 5.509 (anfangs -14.491, am Ende -20.000).
Dank dieser Erklärung ist der Groschen bei mir nun endlich auch bis
auf den Grund gefallen.

Und dafür möchte ich mich nochmals bei Dir ganz herzlich bedanken.

Vielen Dank für Deine Geduld mit mir, ich bin scheinbar manchmal echt
schwer von Begriff. :-)

Andreas.
Bernd P
2009-12-11 17:23:30 UTC
Permalink
Hallo Andreas,
Post by Andreas Killer
...
Und dafür möchte ich mich nochmals bei Dir ganz herzlich bedanken.
...
Gern geschehen.

Viele Gruesse,
Bernd

Andreas Killer
2009-11-28 14:00:10 UTC
Permalink
Allerdings denke ich das dieses Verfahren einen Pferdefuß hat, denn die
Verteilung ist krumm.
Ich hab mich nochmal ein wenig damit beschäftigt und eine Lösung
gefunden, die eine ausgeglichene Verteilung bietet. Damit könnte man
nun auch 110% geben. :-))

Andreas.

Function RundenZuSumme(ByVal Soll As Double, ByVal Stellen As _
Integer, Bereich As Range) As Variant
'Rundet alle Werte in Bereich auf Anzahl Stellen, _
modifiziert die Einzelwerte damit diese als Summe Soll _
ergeben, gibt alle Werte als Matrix zurück
Dim Res(), X As Long, Y As Long, mX As Long, mY As Long
Dim Max As Double, Temp As Double, Summe As Double

'Werte einlesen
Res = Bereich
'Die tatsächliche Summe berechnen
For Y = LBound(Res) To UBound(Res)
For X = LBound(Res, 2) To UBound(Res, 2)
Summe = Summe + Res(Y, X)
Next
Next

'Prozentuale Abweichung zum Soll berechnen
If Summe <> Soll Then
Summe = Soll / Summe
'Vorrunden
For Y = LBound(Res) To UBound(Res)
For X = LBound(Res, 2) To UBound(Res, 2)
Res(Y, X) = WorksheetFunction.Round(Res(Y, X), Stellen)
Next
Next
Else
Summe = 1
End If

'Werte runden
For Y = LBound(Res) To UBound(Res)
For X = LBound(Res, 2) To UBound(Res, 2)
'Abweichung ausgleichen
Res(Y, X) = Res(Y, X) * Summe
'Wert runden
Temp = WorksheetFunction.Round(Res(Y, X), Stellen)
'Die Position des Ausgleichwertes bestimmen
If Max = Empty Then
Max = Res(Y, X) - Temp
mY = Y
mX = X
Else
If Res(Y, X) - Temp > Max Then
Max = Res(Y, X) - Temp
mY = Y
mX = X
End If
End If
'Gerundeten Wert speichern
Res(Y, X) = Temp
'Vom Soll abziehen
Soll = Soll - Temp
Next
Next

'Den Ausgleichwert korrigieren
Res(mY, mX) = Res(mY, mX) + Soll
'Werte zurückgeben
RundenZuSumme = Res
End Function
Thomas Kühn
2009-11-26 12:01:27 UTC
Permalink
Hallo Andreas,
Post by Andreas Killer
Post by Michael Happ
Wie löst man dieses "Anzeigeproblem", so dass ein händisches
Aufsummieren der angezeigten Werte dann auch 100% ergibt?
In dem man nicht rundet sondern die Zellen der Prozentzahlen mit
Prozent und 2 Nachkommastellen formatiert.
Dann sieht man genau das was im OP steht. die Stellen bleiben
ja erhalten, und werden nur nicht angezeigt.
Post by Andreas Killer
Dann gibt auch die Summe der Prozentzahlen 100,00%
Das ist unbestritten. Nur in genau oben genanntem Fall
ist erst ab der 4. Stelle hinter dem Komma die Anzeige so,
dass die Summe auch auf dem Papier 100% ergibt.

Bei 3 Stellen sieht es noch so aus:

115 17,164%
222 33,134%
333 49,701%

Auch das wäre noch 99,999%
Bei 4 Stellen:

115 17,1642%
222 33,1343%
333 49,7015%

Als Lösung ergibt sich also nur, dass mehr Stellen angezeigt
werden, oder damit leben.



Gruß Thomas


--

http://www.thomas-kuehn.de
Bernd P
2009-11-27 12:32:54 UTC
Permalink
Hallo Micha,

Wenn die (auf 2 Nachkommastellen) gerundeten Prozentwerte nicht genau
100 ergeben, hat man immer einen Fehler in der Darstellung. Ziel
sollte es sein, diesen Fehler so klein wie möglich zu halten.

Mein Vorschlag: Verteile 10000 "Sitze" nach dem d`Hondt Verfahren und
teile dann das Ergebnis durch 100:
Falls Deine Eingabewerte in A1:A3 sind, selektiere zum Beispiel die
Zellen B1:B3 und gib als Matrixformel ein:
=dHondt(10000;A1:A3)%

Die Funktion dHondt:
Function dHondt(lSeats As Long, vVotes As Variant) As Variant
Dim i As Long, k As Long, n As Long
Dim vA As Variant, vB As Variant, vR As Variant
Dim dMax As Double

With Application.WorksheetFunction
vA = .Transpose(.Transpose(vVotes))
vB = vA
n = UBound(vA, 1)
ReDim vR(1 To n, 1 To 1) As Variant
ReDim lDenom(1 To n) As Long

Do While i < lSeats
'identify max
dMax = .Max(vB)
k = .Match(dMax, vB, 0)
lDenom(k) = lDenom(k) + 1
vB(k, 1) = vA(k, 1) / (lDenom(k) + 1#)
vR(k, 1) = vR(k, 1) + 1
i = i + 1
Loop
dHondt = vR
End With
End Function

Den Fehler minimierst Du, wenn Du die Eingabedaten vorher nach dem
Rundungsfehler sortierst.

Viele Grüße,
Bernd
Loading...