Zurück   Flashforum > Flash > ActionScript > ActionScript 1

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 17-03-2006, 14:27   #1 (permalink)
Neuer User
 
Registriert seit: Sep 2001
Beiträge: 14
Actioncript mal GENAU RECHNEN lassen ...

Hi!

Es ist ja allgemein bekannt, dass Fließkommarechnungen nur begrenzt genau sind. Actionscript hat (glaube ich) die gleiche Genauigkeit mit float in Java.


Ich habe nun das Problem, dass mir diese Genauigkeit nicht reicht, weil es zu unschönen Rundungsfehlern kommt.

Gibt es IRGENDEINEN Weg genauer zu Rechnen mit Flash?

Ich benutze auch gerne das neuste Flash, das neuste Actionscript oder irgendwelche "perversen" Tricks.
Jedes Mittel ist Recht!
gammaomega ist offline   Mit Zitat antworten
Alt 17-03-2006, 16:24   #2 (permalink)
................
 
Benutzerbild von Der Frager
 
Registriert seit: Jun 2004
Beiträge: 15.890
Guck mal HIER.
Ab Post 12 wird's "interessant" .
__________________

ternärer Konditionaloperator

+++ Bitte keine Privat-Nachrichten bezüglich Flashfragen! +++
Der Frager ist offline   Mit Zitat antworten
Alt 17-03-2006, 22:15   #3 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 18.054
die rechnen alle nach: ieee-754
http://de.wikipedia.org/wiki/IEEE_754

für astronomische berechnungen ist flash wohl nicht geeignet (wegen der fehlenden geschwindigkeit).
falls doch, dann wirst du dir eigene rechenoperationen programmieren müssen:
a)
die zahlen in strings packen und so berechnen
oder

b)
die zahlen aufteilen. z.b.

1111122222333334444455555
wird dann zu 12345 transformirt, wobei
1 = 11111 *10^20 darstellt
2 = 22222 *10^15 usw.

um rundungsfehler in den brüchen zu verringern, keine dezimalstellen sondern die nachkommastelle als bruch speichern und dementsprechend berechnen.
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (17-03-2006 um 22:19 Uhr)
hgseib ist offline   Mit Zitat antworten
Alt 18-03-2006, 10:14   #4 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Wenn ich mit Geld rechnen muss, benutze ich z.B. immer Cent oder 10tel Cent als Basis. Nur für die Ausgabe mache ich dann daraus Euro.

mfg. h
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D
hazy fantazy ist offline   Mit Zitat antworten
Alt 18-03-2006, 13:46   #5 (permalink)
Neuer User
 
Registriert seit: Sep 2001
Beiträge: 14
@hgseib
Wie ich geschieben hatte geht es mir um die Genauigkeit der Fließkommarechnung und nicht um ein Überschreiten des möglichen Zahlenbereichs. Und die Verwendung von IEEE 754 sagt ja nichts über die Genauigkeit aus.

Zu deiner Möglichkeit a):
Meinst du es macht Sinn zu versuchen sämtliche Rechenoperantionen für Strings nachzuimplementieren? Hat das schonmal jemand versucht?

Mit Brüchen rechnen hat einen entscheidenden Nachteil: Man muss kürzen, also dividieren. Bisher muss ich das nicht. Daher habe ich Angst die Pest mit der Cholera auszutreiben.

@hazy fantazy
Die Idee hatte ich auch schon :-)
Ich muss nur leider Geldbeträge mit Faktoren (z.B. 1,75) multiplizieren und dann auf 5 Cent abrunden. Genau da kracht es: Statt 10€ kommt 9.99999999...€ raus und dann rundet er auf 9.95€ ab :-/

Geändert von gammaomega (18-03-2006 um 13:53 Uhr)
gammaomega ist offline   Mit Zitat antworten
Alt 18-03-2006, 15:43   #6 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 18.054
"..Und die Verwendung von IEEE 754 sagt ja nichts über die Genauigkeit aus.."
doch, weil es neben dem zahlenbereich ja auch um die anzahl der signifikanten ziffern geht. also ab welcher stelle die zahlendarstellung abgebrochen wird.

"..sämtliche Rechenoperantionen.."
weiss ja nicht, was du machen willst, langen die 4 grundrechenarten, oder willst du auch wurzel, winkelfunktionen usw. genauer haben?

"..Mit Brüchen rechnen hat einen entscheidenden Nachteil: Man muss kürzen, also dividieren.."
genau das sollst du ja damit vermeiden!
157 / 17 = 9,2352941 == ungenau, weil nach den signifikanten ziffern weitere ziffern folgen müssten.
157 / 17 = 9 4/17 also drei anstatt einer variablen und es wird eben nicht gekürzt, sondern immer der ggT gesucht.

-----------
aber, wie du erst jetzt verrätst willst du 'nur' mit geld rechnen. dann sollte ein vor-runden das 'problem' beheben:
Code:
Number.prototype.fuenfer = function() {
	var rnd = Math.floor(Math.round(this*100)/5)/20;
	return rnd == int(rnd) ? rnd+".00" : rnd*10 == int(rnd*10) ? rnd+"0" : rnd;
};
var a = 9.99999999999999999;
var b = 17.833;
var c = 99.977;
trace(a.fuenfer());
trace(b.fuenfer());
trace(c.fuenfer());
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (18-03-2006 um 15:45 Uhr)
hgseib ist offline   Mit Zitat antworten
Alt 18-03-2006, 19:20   #7 (permalink)
Neuer User
 
Registriert seit: Sep 2001
Beiträge: 14
1.)
IEEE 754 umfasst mehrere Formate und Genauigkeit. Daher ist die Aussage, dass Flash sich nach IEEE 754 richtet keine Aussage darüber welche Genauigkeit nun vorliegt.

2.)
Eigentlich reichen +,-,*
Aber die Multiplikation auf Strings nachzubauen stelle ich mir wenig spaßig vor.
Machbar wäre es wohl....

3.)
Klar muss ich den ggT berechnen, dass ist ja easy. Aber danach muss ich ja Zähler und Nenner durch den ggT dividieren um zu Kürzen. Bisher muss ich wie gesagt niergendwo Dividieren.
Wenn man 2 Ganzzahlen dividiert und die Ganzzahl-Division ohne Rest möglich ist: Darf man sich darauf verlassen, dass Flash eine Ganzzahl-Division mit absolute Genauigkeit durchführt? Oder kann man irgendwie eine Ganzzahl-Division erzwingen?
Unter JAVA ist int/int = int. Unter AS ja leider nicht.

4.)
Ob es nun Geld ist spielt ja keine so große Rolle.
Aber es beschränkt sich in der Tat auf 2 Nachkommastellen.

Ich habe mir mal erlaubt deinen Code in eine anständige Form zu bringen:

Code:
Number.prototype.fuenfer = function() {
	var cent = Math.round(this*100); //int
	var fivecents =  Math.floor(cent/5); //int
	var euro = fivecents / 20; //float
	
	if (euro == int(euro)) { //keine nachkommastellen
		return euro+".00";
	}
	else if (euro*10 == int(euro*10)) { //eine nachkommastelle
		return euro+"0";
	}
	else {
		return euro;
	}
};

var a = 9.99999999999999999;
var b = 17.833;
var c = 99.977;

trace(a.fuenfer());
trace(b.fuenfer());
trace(c.fuenfer());
In der Tat funktionier dies in den gezeigten Beispielen.
Aber ich muss ja einen Geldbetrag mit mehreren Faktoren multiplizieren bevor ich runden darf/muss. Da können ja schon Fehler passieren, die schwer vorherzusagen sind.
gammaomega ist offline   Mit Zitat antworten
Alt 18-03-2006, 20:03   #8 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 18.054
"..in eine anständige Form zu bringen.."
wusste nicht, das mein script unanständig ist ;-)

"..Da können ja schon Fehler passieren, die schwer vorherzusagen sind.."
ja
sag mir bescheid, wenn's soweit ist.
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de
hgseib ist offline   Mit Zitat antworten
Alt 18-03-2006, 23:49   #9 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
3.) Ja, das darfst du.
Zumindest solange du nicht immens grosse Zahlen benutzt. Am anderen Ende der Fahnenstange gibt es nämlich auch wieder Lücken.

mfg. h.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (18-03-2006 um 23:57 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 19-03-2006, 10:26   #10 (permalink)
Neuer User
 
Registriert seit: Sep 2001
Beiträge: 14
@hgseib
hehe
Das man so keinen code schreibt sollte jedem Entwickler klar sein:
Code:
return rnd == int(rnd) ? rnd+".00" : rnd*10 == int(rnd*10) ? rnd+"0" : rnd;
Zitat:
wenn's soweit ist.
Es ist immer "soweit". Meine Frage bezog sich ja urspünglich auf eine generelle Erhöhung der Genauigkeit.

@hazy fantazy
Das ich ein Problem mit der Genauigkeit und nicht mit zu großen oder zu keinen Zahlen habe hatte ich ja schon geschrieben.

-=Fazit=-
Es scheint so zu sein, dass man die Genauigkeit nicht generell erhöhren kann.
Es gibt einmal den Code von hgseib, der "etwas geschickter" rundet. Ob dadruch immer richtig gerechnet wird lässt sich schwer beweisen. ein Gegenbeispiel:
9,995 würde fälschlicherweise auf 10 gerundet und nicht auf 9,95€.

Strings zu benutzen würde es nötig machen +,-,* selbst zu implementieren. Da stellt sich die Frage wie performant das Ganze nachher noch bleibt.

Bleibt die Idee mit Brüchen zu rechnen.
a/b muss aber gekürzt werden, was Division nötig macht.
Laut "hazy fantazy" rechnet Flash mt INTs genau.
Also ist (a-(a%b))/b eine präzise Rechnung. Bleibt ein Rest von (a%b)/b.
Spätestens am Ende muss zur Ausgabe dieser Bruch auf b = 10 gebracht werden. Wenn man dies einfach durch Division ausrechner besteht wieder die Gefahr der Ungenauigkeit.
gammaomega ist offline   Mit Zitat antworten
Alt 19-03-2006, 11:08   #11 (permalink)
Herr Brot
 
Benutzerbild von mati
 
Registriert seit: Dec 2002
Beiträge: 1.692
Zitat:
Zitat von gammaomega
9,995 würde fälschlicherweise auf 10 gerundet und nicht auf 9,95€.

9,995 gerundet auf 2 Nachkommastellen IST 10,00. Oder was für ne Rundung möchtest du da realisieren?
__________________
„Ich war geheilt, all right!“
mati ist offline   Mit Zitat antworten
Alt 19-03-2006, 11:09   #12 (permalink)
Neuer User
 
Registriert seit: Sep 2001
Beiträge: 14
siehe posting #5:
ABrunden!
gammaomega ist offline   Mit Zitat antworten
Alt 19-03-2006, 11:18   #13 (permalink)
Herr Brot
 
Benutzerbild von mati
 
Registriert seit: Dec 2002
Beiträge: 1.692
ah ja!
__________________
„Ich war geheilt, all right!“
mati ist offline   Mit Zitat antworten
Alt 19-03-2006, 11:55   #14 (permalink)
Nagelneuer User
 
Benutzerbild von hazy fantazy
 
Registriert seit: Dec 2005
Beiträge: 923
Es gibt nach meiner Erfahrung keine allgemein gültigen Regeln, wie man mit der Ungenauigkeit umgehen kann. Es ist sehr applikationsspezifisch, an welchen Stellen du rundest.
Wenn du z.B. eine Liste von gerundeten Zahlen darstellst, die aufsummiert werden sollen, dann musst du dich entscheiden, ob du die Summe der aufgerundeten oder der originalen Zahlen aufsummierst. Die Genauigkeit würde es erfordern, die originalen Zahlen zu addieren. Der User wäre aber wahrscheinlich irritiert, wenn sein Taschenrechner für 1,50 ein anderes Ergebnis als dein Programm ausgibt.
Deshalb bleibt einem eigentlich nur, von Fall zu Fall zu entscheiden, denn dieses Problem hast du ja immer sobald die Anzeige von der absoluten Genauigkeit abweicht.

wg. zu grossen Zahlen
Das Problem tritt auch dann auf, wenn du Bruchrechnung benutzt und zwischendurch nicht kürzt oder nicht kürzen kannst


mfg. h.
__________________
The fact that you've got "Replica" written on the side of your gun and the fact that I've got "Desert Eagle written on the side of mine ... :D

Geändert von hazy fantazy (19-03-2006 um 11:57 Uhr)
hazy fantazy ist offline   Mit Zitat antworten
Alt 19-03-2006, 13:27   #15 (permalink)
Techniker
 
Benutzerbild von hgseib
 
Registriert seit: Sep 2003
Ort: 64807
Beiträge: 18.054
"..Das man so keinen code schreibt sollte jedem Entwickler klar sein:.."
das ist, mit verlaub, totaler blödsinn!!!
diese syntax ist genauso wie if.. while.. switch.. usw. voll korrekt. oder habe ich da etwas verpasst? hat bush die 'achse des bösen' neu definiert? wer x ? true : false; benützt muss mit einem überfall der amis rechnen?
wer lesen kann, der kann lesen. wer es nicht kann, der kann halt nicht lesen. wer programmieren kann, der kann das verstehen. wer nicht programmieren kann, der kann auch die aufgeblasenen 300 zeilen nicht verstehen - oder etwas dazulernen.
bliebe bestenfalls noch eine erklärende zeile. da es hier NUR um dieses problem geht ist die nicht notwendig. und hier ist auch nicht die 'krabbel-ecke', dass man jede erklärung bei 'adam und eva' anfangen muss. dann poste bei den einsteigern. bzw. ich muss ja nicht alles verraten ;-)

'Es ist immer "soweit".'
und leider albern. welche antwort erwartest du auf so eine allerweltsfrage? das, wenn man aus einer zahl 3000mal die 975ste wurzel zieht, 17+4 addiert, noch 10000mal logaritmiert und daraus sinus berechnet, die rundungsfehler das endergebnis merklich verändern? darüber brauchen wir hier nicht zu diskutieren.
benenne einen konkreten fall, dann kann man sich gedanken darüber machen, ob sich dabei die rundungsfehler der zahlendarstellung merklich auswirken können.

'Meine Frage bezog sich ja urspünglich auf eine generelle Erhöhung der Genauigkeit'
darauf hasst du ursprünglich von mir lösungsansätze erhalten, die dir offensichtlich zu viel arbeit beinhalten?

"9,995 würde fälschlicherweise auf 10 gerundet und nicht auf 9,95€."
dann musst du nur definieren, ab wann du hoch bzw. runter runden willst. der computer kann das nicht riechen.
bzw. mein script war nur eine anregung, ein bisschen eigeninitiative anstatt immer nur 'get nicht' zu sagen, ware auch mal ganz nett ;-)
Code:
Number.prototype.preisstaffel = function(runden_auf, abrunden) {
	var fc = abrunden ? Math.floor : Math.ceil;
	if (!runden_auf) return fc(this);
	var s = -(int(Math.log(runden_auf)/Math.LN10));
	do {
		var n = Math.pow(10, ++s);
		var r = runden_auf*n;
	} while (int(r) != r);
	// faktor m bestimmt, ab wann vorgerundet wird: beispiel b und c
	var m = n*1000;
	var rnd = fc(Math.round(this*n*m)/r/m)*r;
	if (s<0) return rnd/n;
	rnd = String(rnd).substr(0, -s)+"."+String(rnd).substr(-s);
	return rnd.split("-.").join("-0.");
};
var a = 9.99999999999999999;
var b = 9.999999995;
var c = 9.99999995;
var d = -0.8368;
var e = 9999.977;
var f = 12345678;
var g = 901.44339;
trace(a+" => "+a.preisstaffel(.05, true));
trace(b+" => "+b.preisstaffel(.05, true));
trace(c+" => "+c.preisstaffel(.05, true));
trace(d+" => "+d.preisstaffel(.005, true));
trace(e+" => "+e.preisstaffel(.5, true));
trace(f+" => "+f.preisstaffel(2000, false));
trace(g+" => "+g.preisstaffel(0, false));
trace(g+" => "+g.preisstaffel(.125, true));
__________________
die ultimative antwort auf alle programmierfragen: der debugger
mfg h.g.seib www.SeibsProgrammLaden.de

Geändert von hgseib (19-03-2006 um 22:25 Uhr)
hgseib ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 15:22 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2014 Marc Thiele