Einkommensteuer in Matlab < Matlab < Mathe-Software < Mathe < Vorhilfe
|
Ich habe diese Frage in keinem Forum auf anderen Internetseiten gestellt.
Ich arbeite das erste Mal mit einem Programm wie Matlab und hab auch sonst keine Programmierkenntnisse.
Ich würde gerne Steuerfunktionen (wie die Einkommensteuer) in Matlab zeichnen (später auch schneiden etc.) habe aber Probleme bei der Progammierung.
Eine solche Funktion laienhaft wiedergegeben schaut beispielsweise so aus:
x=Bemessungsgrundlage
y=Steuer
solange x kleiner als 10000; y=0
x ist zwischen 10000 und 25000 y=((x10.000)*5.750)/15.000
usw...
Um die Progressionsstufen zu berücksichtigen habe ich mich ein wenig mit "if"-Befehlen gespielt, bin aber auf keine zufriedenstellenden Ergebnisse gekommen.
Ich hoffe jemand kann mir einen guten Ansatz liefern.
|
|
|
|
Hallo,
um das Schreiben einer kleinen Funktion kommt man da wohl nicht herum.
Du kannst es ja damit versuchen:
1: | function piece = piecewise(xval, intervals, funcStrings, less_equal);
| 2: | %PIECEWISE stückweise Definition von Funktionen mit einer Variablen
| 3: | % xval Matrix oder einzelner Wert, auf den die stückweise definierte
| 4: | % Funktion angewandt werden soll.
| 5: | % intervals Zeilenvektor mit Intervallgrenzen
| 6: | % funcStrings cellArray mit Strings, die die Teilfunktionen darstellen
| 7: | % less_equal (optional) Schalter, der die Auswertung per "kleiner/gleich"
| 8: | % statt "kleiner" einschaltet.
| 9: |
| 10: | %Argumentenüberprüfung
| 11: | if nargin<4 less_equal = 0; end
| 12: | if (any(intervals==sort(intervals)) == 0) error('Intervallgrenzen in unsortierter Reihenfolge!'); end;
| 13: | if size(intervals,2) + 1 ~= size(funcStrings,2) error('Nicht alle Fälle sind abgedeckt!'); end;
| 14: | if (less_equal) findString = '[find(x<=intervals) size(intervals,2)+1]'; else findString = '[find(x<intervals) size(intervals,2)+1]'; end;
| 15: | %Argumentenüberprüfung ENDE
| 16: |
| 17: | for i=1:size(xval,1),
| 18: | for j=1:size(xval,2),
| 19: | x=xval(i,j);
| 20: | cond_ok = eval(findString);
| 21: | piece(i,j) = eval(char(funcStrings(cond_ok(1))));
| 22: | end;
| 23: | end; |
Ich hänge die Datei mal an: Datei-Anhang
Einfach als "piecewise.m" im aktuellen(!) Verzeichnis speichern.
Der Aufruf in Matlab sieht dann z.B. so aus:
piecewise(15000 , [10000,25000],{'0','((x-10000)*5750)/15000','x'})
falls du den Wert für eine einzelne Eingabe berechnen willst oder
piecewise(0:100:30000 , [10000,25000],{'0','((x-10000)*5750)/15000','x'})
falls du die Werte für Eingaben von 0 bis 30000 in Hunderterschritten berechnen willst.
Die einzelnen Argumente:
1. Eingabe
2. Zeilenvektor mit Intervallgrenzen. Dabei wird immer mit "wenn x < Intervallgrenze dann..." gerechnet. Die Intervallgrenzen müssen (natürlich) aufsteigend sortiert sein.
3. cellArray mit entsprechenden Formeln. Kümmere dich nicht um das "cellArray". Hauptsache, du setzt das Ganze in geschweifte Klammern und trennst die einzelnen Formeln durch Semikolons.
Wichtig ist, dass es immer eine Formel mehr gibt als Intervallgrenzen. Die letzte Formel wird dann ausgewertet, falls die Eingabe größer ist als die größte Intervallgrenze.
4. Optional: Falls dieses Argument auf 1 gesetzt wird, dann wird mit "wenn x <= Intervallgrenze dann..." gerechnet.
Ich hoffe, das ist so in etwa das, was du benötigst.
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: m) [nicht öffentlich]
|
|
|
|
|
Also zunächst mal ein großes Dankeschön für Deine Mühe.
Da Du es aber mit einem richtigen "noob" zu tun hast, kann ich nicht allzuviel damit anfangen. Klar, Datei hab ich gespeichert, und ich schaff es sogar diese aufzurufen.
Nur, weiterarbeiten kann ich damit leider nicht.
Mir geht es darum den einfachsten aller Ansätze zu finden, um damit selbständig weiterarbeiten zu können.
Autodidaktisch hab ich bisher zB für den Bereich zwischen 10000 und 25000 ein m-file in der Form
x=0.1:0.1:25000
y=(x-10000)*5750/15000
plot(x,y)
gebastelt.
Was dabei halt noch fehlte, war, dass solange x<10000 y=0;
darum wollte ich eine if-Bedingung
etwa in der Form
x=0.1:0.1:25000
if x<10000
y=0
else
y=(x-10000)*5750/15000
end
plot(x,y)
einbauen,
was aber nicht so recht klappen wollte.
Jetzt meine Frage: Lässt sich mit meinem naiven Ansatz weiterarbeiten oder muss ich mich wohl oder übel eingehensd mit dem vorgeschlagenen Ansatz beschäftigen?
|
|
|
|
|
Hallo,
dann mal zunächst zu deinem Ansatz:
Man kann ihn benutzen, nur muss man da mit einer for-Schleife arbeiten, da Matlab sonst verschiedene Anweisungen gleichzeitig abarbeiten können müsste (verschiedene Zweige von if...else..end).
x=0.1:0.1:25000
for i=1:size(x,2),
if x(i)<10000
y(i)=0;
else
y(i)=(x(i)-10000)*5750/15000;
end;
end;
plot(x,y)
Der Vorteil meines Codes ist eben nur:
**** WERBEEINBLENDUNG ****
Wenn sich die Anzahl der Stufen ändert (Steuerreform oder so), muss der Code nicht verändert werden -> keine Extra-if-Blöcke.
Außerdem benötigt man immer nur einen Aufruf.
Das Plotten ist auch nicht schwer:
xvals = 0:10:15000;
yvals = piecewise(xvals,[10000],{'0','((x-10000)*5750)/15000'});
plot(xvals,yvals);
**** ENDE DER WERBEEINBLENDUNG ****
Ach ja, mit Schritten von 0.1 dauert es etwas lange. Musst du wirklich so kleinschrittig rechnen?
Gruß
Martin
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 18:22 Mo 06.11.2006 | Autor: | stanzieta |
Nein, so kleinschrittig isses ned nötig!
Wenn ich mehr Zeit hab, werde ich mich genauer mit deinen Vorschlägen beschäftigen; erstmal Danke und einen Schönen Abend noch
|
|
|
|
|
Das heißt also, mithilfe Deiner Funktion kann ich beliebig viele Progressionsstufen einbauen und auch die Grenzen immer ändern und das alles nur mit der piecewise (.....) Abfrage, während das .m file stets gleich bleibt?
Das klingt ja fast nach einer eierlegenden Wollmilchsau :)
Könntest du mir noch ein Beispiel liefern, wie ich Schnittpunkte 2er solcher verschiedener Steuerfunktionen berechnen und graphisch darstellen kann?
Viele Dank im voraus.
|
|
|
|
|
Hallo,
die Bestimmung von Schnittpunkten hat ihre Tücken. Aber stückweise definierte Funktionen machen es Matlab nicht gerade leicht.
Aber fangen wir mal vorne an:
Das Beispiel:
Zwei, äääh, Handytarife sind gegeben: tarif1 und tarif2:
tarif1string = 'piecewise(x,[20,25,50],{''0.25*x'',''5+2*(x-20)'',''15'',''15+2*(x-50)''})'
tarif2string = 'piecewise(x,[15,30,40],{''8/15*x'',''8+2/15*(x-15)'',''10+(x-30)'',''20+0.5*(x-40)''})'
Hier mal der Plot:
x = 0:80
plot(eval(tarif1string),'b')
hold on
plot(eval(tarif2string),'r')
[Dateianhang nicht öffentlich]
Nun wollen wir fzero benutzen. Diese Funktion sucht Nullstellen entweder in der Nähe einer vorgegebenen Stelle oder innerhalb eines Intervalls, an dessen Grenzen die Funktion UNTERSCHIEDLICHE Vorzeichen haben muss. Etwas Vorwissen ist also schon vonnöten. Man sollte sich also mindestens die Graphen anschauen.
Nun müssen wir noch die Funktion bilden, deren Nullstellen wir suchen wollen. Das ist natürlich die Differenz der beiden Tarife. Das machen wir auch als String:
diffString = strcat(strcat(tarif1string,'-'),tarif2string)
Nun können wir nach einer Nullstelle in einem Intervall suchen:
fzero(inline(diffString),[20,30])
oder wir suchen in der Nähe einer Schätzung:
fzero(inline(diffString),25)
Einfacher scheint es nicht zu gehen...
Man könnte natürlich automatisch alle Vorzeichenwechsel und somit die Suchintervalle für fzero() bestimmen. Die Ergebnisse könnte man alle in einen Vektor packen und plotten.
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: jpg) [nicht öffentlich]
|
|
|
|
|
So weit so gut, ich denke bisher habe ich alles verstanden (bis auf das .m-file, aber das soll mich nicht weiter kümmern).
Im Besonderen beschäftige ich mich jedoch mit der Erbschaftsteuer, und diese hat leider so ihre Tücken. Die Funktion hat genauso ihre Progressionsstufen, jedoch sind nicht wie bei der Einkommensteuer Grenzsteuersätze (bzw anstatt dessen gleich Formeln für die einzelnen Stufen gegebebn) sondern nur die einzelnen Stufen.
Soll heißen:
zB bis EINSCHLIEßLICH 7300 2%
bis EINSCHLIEßLICH 14600 2,5%
.
.
.
Das Problem ist nun, wenn also x=7301 blieben ihm 7301*0,0975=7118,475
bei x=7299 bleiben 7299*0,98=7153,02, und damit mehr, übrig, was ja unlogisch ist.
Daher gibt es einen Zusatzartikel:
"Die Steuer [....] ist in der Weise zu berechnen, dass von dem Wertbetrag des Erwerbes nach Abzug der Steuer nicht weniger erübrigt wird, als von dem höchsten Wertbetrage der nächstniedrigeren Stufe des Tarifes nach Abzug der nach dieser entfallenden Steuer."
Klingt kompliziert, heißt aber nichts anderes, als dass bei x=7301 nun doch nicht 2,5%*7301, sondern nur 7301-(7300*0,98)=147. (Damit 7154 Euro übrig bleiben). Diese Grenze bleibt solange bestehen bis
x*(1-0,025)>7154.
also bei 7337,435897
Für diese eine Grenze müsste die Formel mit
piecewise(7338, [7300,7337.435897],{'x*0.02','x-(7300*0.98)','x*0.025'})
ja eigentlich passen, oder?
Ob sie nun stimmt oder nicht, bestimmt kann man mit irgendwelchen min/max Bedingungen das einfacher gestalten, denk ich.
|
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 11:51 Di 07.11.2006 | Autor: | stanzieta |
Achja, ich Frage deshalb weil ich es mit ziemlich vielen solcher Grenzen zu tun habe.
Allein das österreichische Gesetz kennt 16 Progressionsstufen und 5 Steuerklassen; also müsste ich 80 solcher Grenzen ausrechnen.
Die deutsche Fassung beeinhaltet zwar weniger, aber im noch ausreichend viele Grenzen.
|
|
|
|
|
"Der Spaß geht weiter" ist gut. Kein Wunder, dass mein Geld immer weniger wird. Bei diesen Regeln...
Aber nichtsdestotrotz: Dem Informatikör ist nichts zu schwör!
Du gibst die einzelnen Grenzbeträge und Steuerstufen an und meine neue Hilfsfunktion spuckt dir eine altbekannte "piecewise"-Funktion aus.
Ich mache das mal vor:
Eingabe:
s2p = stufen2piecewise([7300,14600,21900],[2,2.5,3,3.5])
liefert mir:
s2p = piecewise(x,[7300,7337.4359,14600,14675.2577,21900],{'0.02*x','x-7154','0.025*x','x-14235','0.03*x','0.035*x'})
Nun definiere ich mir:
x=0:100:30000;
und plotte unser Steuermodell:
plot(x,eval(s2p));
Ergebnis:
[Dateianhang nicht öffentlich]
Das Ganze funktioniert so:
1: | function res = stufen2piecewise(grenzen, stufen)
| 2: | %STUFEN2PIECEWISE Erzeugt aus der Angabe von Steuerstufen eine stückweise
| 3: | % definierte Funktion, die Einkommen auf Steuerbetrag abbildet (als String)
| 4: | % Detailed explanation goes here
| 5: | % grenzen Zeilenvektor mit Grenzbeträgen als Zahlen
| 6: | % stufen Zeilenvektor mit Steuersätzen (in Prozent) als Zahlen
| 7: |
| 8: | stufen = stufen / 100;
| 9: | for i=1:size(grenzen,2)-1,
| 10: | zwischengrenzen(i)=grenzen(i)*(1-stufen(i))/(1-stufen(i+1));
| 11: | subtr=grenzen(i)*(1-stufen(i));
| 12: | zwischenstufen(i)=cellstr(strcat('x-',num2str(subtr)));
| 13: | end;
| 14: |
| 15: | stufen_neu = '''';
| 16: | grenzen_neu = '';
| 17: | loop_end = size(grenzen,2)-1;
| 18: | for i=1:loop_end,
| 19: | grenzen_neu = [grenzen_neu num2str(grenzen(i)) ',' num2str(zwischengrenzen(i)) ','];
| 20: | stufen_neu = [stufen_neu num2str(stufen(i)) '*x' ''',''' char(zwischenstufen(i)) ''','''];
| 21: | end;
| 22: | grenzen_neu = [grenzen_neu num2str(grenzen(i+1))];
| 23: | stufen_neu = [stufen_neu num2str(stufen(i+1)) '*x'',''' num2str(stufen(i+2)) '*x'''];
| 24: |
| 25: | res = strcat('piecewise(x,[',grenzen_neu);
| 26: | res = strcat(res,'],{');
| 27: | res = strcat(res,stufen_neu);
| 28: | res = strcat(res,'})'); |
Aber ich hänge die Datei natürlich wieder an...
stufen2piecewise.m
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: jpg) [nicht öffentlich] Anhang Nr. 2 (Typ: m) [nicht öffentlich]
|
|
|
|
|
Ui ui ui, wieder so eine wunderschöne Lösung.
Die nächsten Dinge die ich benötige, wären die Berechnung und grafische Wiedergabe der Grenz- und Durchschnittsteuersätze.
Also 1. Ableitung und f(x)/x.
P.S. Also das frag ich wirklich nur aus Bequemlichkeit....aber....für den Stufentarif hast du mir so eine schöne Funktion gebastelt, bei der ich nur Grenzen und Sätze, also [7300,14600...] (2.5,3...) eingeben muss und die "Zusatzgrenzen" sowie Formeln selbständig berechnet werden.
Für die "normale" Einkommensteuer muss ich weiterhin Grenzen und dazugehörige Formeln eingeben.
Also wenns leicht geht, aber wirklich nur dann, wäre auch hier eine Funktion toll, bei der man nur Grenzen und Grenzsteuersätze eingeben muss. dh statt
piecewise (x, [10000,25000,51000],{'0','((x-10000)*5750)/15000','((x-25000)*11335/26000+5750)','((x-51000)*0.5+17085)'})
etwa piecewise(x, [10000,25000,51000],{'0','0.23','0.335','0.5'})
|
|
|
|
|
Hallo,
zuerst zur Ableitung:
Die kriegen wir eigentlich nur als Näherung durch Differenzenquotient hin. Alles andere wäre sehr aufwändig. Aber bei den einfachen Teilfunktionen sollte das kein Problem sein...
Unsere Funktion sei mal:
funk = stufen2piecewise([10000,25000,50000],[0,2.5,4,6.5]);
Wir wählen uns ein kleines (aber nicht zu kleines h):
h = 10;
Nun werten wir die Funktion zweimal aus:
x= h:h:60000+h;
funk2 = eval(funk);
x= 0:h:60000;
funk1 = eval(funk);
funkabl = (funk2-funk1)/h;
plot(x,funkabl);
Ggf. ist es nötig, die y-Achse wegen der großen Sprünge zu skalieren. Das geht (nach dem Plot) mit:
axis([x(1) x(end) 0 1]);
Wir erhalten:
[Dateianhang nicht öffentlich]
Nun zu f(x)/x. Nach der Definition von x und funk:
plot(x,eval(funk)./x);
Wir erhalten:
[Dateianhang nicht öffentlich]
Das P.S. werde ich auch noch bearbeiten...
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: jpg) [nicht öffentlich] Anhang Nr. 2 (Typ: jpg) [nicht öffentlich]
|
|
|
|
|
Hallo,
jetzt zu deinem P.S.:
Die neue Funktion heißt "grenzsts2piecewise" und wird wie gewohnt aufgerufen:
g=grenzsts2piecewise([10000,25000,51000],[0,23,33.5,50]);
Die Ausgabe sieht etwas umständlich aus, weil sie eben auf einer Formel für alle Intervalle beruht. Scheint aber zu funktionieren.
mit x=0:100:60000 plotten wir:
plot(x,eval(g));
und erhalten:
[Dateianhang nicht öffentlich]
So sieht das Ganze im Innern aus:
1: | function res = grenzsts2piecewise(grenzen, grenzsteuersaetze)
| 2: | %GRENZSTS2PIECEWISE Erzeugt aus der Angabe von Grenzsteuerätzen eine stückweise
| 3: | % definierte Funktion, die Einkommen auf Steuerbetrag abbildet (als String)
| 4: | %
| 5: | % grenzen Zeilenvektor mit Grenzbeträgen als Zahlen
| 6: | % grenzsteuersaetze Zeilenvektor mit Grenzsteuersätzen (in Prozent) als Zahlen
| 7: |
| 8: | grenzsteuersaetze = grenzsteuersaetze / 100;
| 9: |
| 10: | stufen_neu = '';
| 11: | grenzen_neu = '';
| 12: |
| 13: | loop_end = size(grenzen,2);
| 14: | grenzen = [0 grenzen];
| 15: | grenzsteuersaetze = [0 grenzsteuersaetze];
| 16: | for i=1:loop_end,
| 17: | stufen_neu = [stufen_neu sprintf('''(x-%d)*(%d*%d-%d*%d)/(%d-%d)+%d*%d'' ,', [grenzen(i), grenzsteuersaetze(i+1), grenzen(i+1), grenzsteuersaetze(i), grenzen(i), grenzen(i+1), grenzen(i), grenzen(i), grenzsteuersaetze(i)])];
| 18: | grenzen_neu = [grenzen_neu sprintf('%d ',grenzen(i+1))];
| 19: | end;
| 20: | stufen_neu = [stufen_neu sprintf('''(x-%d)*%d+%d*%d'' ', [grenzen(i+1), grenzsteuersaetze(i+2), grenzen(i+1), grenzsteuersaetze(i+1)])];
| 21: | grenzen_neu = grenzen_neu(1:end-1);
| 22: |
| 23: | res = strcat('piecewise(x,[',grenzen_neu);
| 24: | res = strcat(res,'],{');
| 25: | res = strcat(res,stufen_neu);
| 26: | res = strcat(res,'})'); |
Und hier noch die Datei:
grenzsts2piecewise.m
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: jpg) [nicht öffentlich] Anhang Nr. 2 (Typ: m) [nicht öffentlich]
|
|
|
|
|
Aufgabe | Verschieben der Funktion nach rechts |
Nochmals danke für deine stets schnellen und superbrauchbaren Antworten.
Normalerweise wär jetzt mindestens schon die 2. Kiste Bier für dich fällig, so sehr helfen mir deine Antworten weiter.
Ich brauch die ganzen Sachen für meine Diplomarbeit (die meisten Berechnungen mach ich im Excel, weil ich mich da besser auskenn; aber Sachen wie das plotten oder das Berechnen von Schnittpunkten gehen in Matlab einfach besser).
Hier ein Beispiel: Erbschaften an Enkelkinder fallen in Deutschland unter die Steuerklasse I, in Österreich unter Steuerklasse II.
(ich find jetzt leider grade ned, wie ich die Datei anhängen kann, aber dank dir hab ich eine schöne Grafik); jedenfalls isses bis 29514 Euro in Österreich "billiger", danach bis 43800 Euro gleich, dann ist man bis 53238 Euro besser Deutscher, danach wieder Österreicher, ab 73820 Euro wieder Deutscher und ab 13.805.640 Euro endgültig Österreicher. (wenn man das Ziel der Steuerminimierung verfolgt)...
Nun sind in all diesen Funktion leider keine Freibeträge berücksichtig.
Der Freibetrag für Enkelkinder zB beträgt in Deutschland 205.000 Euro; in Österreich nur 2.200 Euro. Diese Freibeträge bewirken ja nur, dass sich die jeweilige Funktion um den jeweiligen Freibetrag nach rechts verschiebt.
Hast du dafür eine einfach Lösung parat?
Dateianhänge: Anhang Nr. 1 (Typ: fig) [nicht öffentlich] Anhang Nr. 2 (Typ: fig) [nicht öffentlich]
|
|
|
|
|
Hallo,
sollte ich mal einen Betrag mit vielen Nullen erben, weiß ich ja, an wen ich mich wende...
Ich dachte, für das Freibetragsproblem (so wie ich es verstanden habe!) braucht man keine neue Funktion. Ich demonstriere das mal:
Eine imaginäre Steuer:
steuer=stufen2piecewise([10000,25000,50000],[0,2.5,4,6.5]);
Jetzt sei unser Freibetrag mal bei 2000. Also tippen wir die magische Zeile:
steuer_mit_FB = strrep(steuer, 'piecewise(', sprintf('piecewise(-%d+', 2000))
(Du musst nur immer "steuer" durch deine ursprüngliche Funktion und "2000" durch den Freibetrag ersetzen, klar, oder?)
Und im Plot sieht es so aus (nach Abzug des Freibetrags = rot):
x=0:100:30000;
plot(x, eval(steuer));
hold on;
plot(x, eval(steuer_mit_FB), 'r');
[Dateianhang nicht öffentlich]
Ich hoffe, das war gemeint...
Gruß
Martin
Dateianhänge: Anhang Nr. 1 (Typ: jpg) [nicht öffentlich]
|
|
|
|