Entwickler-Ecke
Sonstiges (Delphi) - Nachkommaanteil als Ganzzahl ermitteln?
herby - Fr 15.12.06 19:18
Titel: Nachkommaanteil als Ganzzahl ermitteln?
hi,
gibt es eigentlich eine Funktion um den Nachkommaanteil als Ganzzahl zu ermitteln?
soll heissen
12.33 --> 33
0.1234 --> 1234
usw..
mit frac bekomm ich ja schon mal den Nachkommaanteil in Form 0.33 bzw 0.1234
über die Anzahl der Kommastellen könnte man ermitteln wie oft mit 10 multipliziert werden muss.
...aber zuerst müsste man mal die Anzahl der Kommastellen rauskriegen.
hmm...Ich gehe das ganze vermutl. vieeeel zu kompliziert an.
Gibt es da vielleicht nicht schon eine fertige math. Funktion?
danke für jede Hilfe
---------
Jetzt momentan mach ich als Notlösung eine FloatToStr und suche mir über die Pos des DecimalSeparator den hinteren Teil und dann zurück als Integer. Naja... nicht gerade sehr schön :? ...
stifflersmom - Fr 15.12.06 20:09
Dein Operator ist mod,
F1 ist Dein friend...
Moin
herby - Fr 15.12.06 20:30
hi, danke erstmal für die rasche Antwort
Zitat: |
Der Operator mod liefert den Rest, der sich bei der Division seiner Operanden ergibt. Das bedeutet: x mod y = x – (x div y) * y. wobei x und y integerwerte darstellen. |
hmm... weiss jetzt leider nicht genau wie mir das weiterhelfen soll.
die übergabewerte sind Integer. soll das heissen ich muss zuerst alles hochmultiplizieren?
wobei wir wieder bei der Frage sind mit was?? (anzahl der nachkommastellen können sich ja ändern)
wie könnte ich denn mod einsetzen zB. bei 0.1234 (etwa 1234 mod 10000 ? - das gibt -2.092) weiss da nicht genau was in meinem Fall die Operanden eigentlich wären.
tschuldigung.. ich bring das noch nicht ganz auf die Reihe :oops:
zongo-joe - Fr 15.12.06 20:36
wenns nur um die Anzahl der Nachkommastellen geht:
so ausm Kopf:
anzahlNachkommastellen := length(floattostr(zahl-trunc(zahl)))-2;
auch keine elegante Lösung, sollte aber funzionieren
Heiko - Fr 15.12.06 20:38
Es geht z.B.:
Delphi-Quelltext
1: 2: 3: 4: 5:
| Nachkomme:=0; while frac(YourNumber)>0 do begin inc(Nachkomme); end; |
PS: Mod dürfte ungeeignet sien, da mod IMHO nur mit Ganzzahl umgehen kann
zongo-joe - Fr 15.12.06 20:42
@Heiko: ich fürchte das ist ne endlosschleife, YOURNUMBER ändert sich ja nicht, oder steh ich da auffer Leitung ?
herby - Fr 15.12.06 21:14
Ich hab befürchtet das dies nicht ohne Schleife geht. :(
meine Not-Lösung sieht so aus
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function FracToInt(d: double): integer; var s: string; p: integer; begin s := Floattostr(d); p := pos(DecimalSeparator,s); if p > 0 then result := StrToIntDef(copy(s,p+1,length(s)-p),0) else result := 0; end; |
na ja.. wie gesagt.. nicht so richtig elegant;
Heiko - Fr 15.12.06 21:23
zongo-joe hat folgendes geschrieben: |
@Heiko: ich fürchte das ist ne endlosschleife, YOURNUMBER ändert sich ja nicht, oder steh ich da auffer Leitung ? |
Jupp, vergessen ;).
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| Nachkomme:=0; while frac(YourNumber)>0 do begin inc(Nachkomme); YourNumber:=YourNumber*10; end; |
GSE - Fr 15.12.06 21:32
wie wär's damit?
mit Pos() die Position des Punkts / Kommas rausfinden und dann einfach Copy ab dort
mfg
GSE
herby - Fr 15.12.06 21:43
GSE hat folgendes geschrieben: |
wie wär's damit?
mit Pos() die Position des Punkts / Kommas rausfinden und dann einfach Copy ab dort
mfg
GSE |
Hab ich ja auch oben schon gemacht und gepostet ;)
herby hat folgendes geschrieben: |
meine Not-Lösung sieht so aus Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function FracToInt(d: double): integer; var s: string; p: integer; begin s := Floattostr(d); p := pos(DecimalSeparator,s); if p > 0 then result := StrToIntDef(copy(s,p+1,length(s)-p),0) else result := 0; end; |
na ja.. wie gesagt.. nicht so richtig elegant; |
@heike - danke, hmm... aber wenn ich da eh durch die Kommastellen durchsteppen muss, kann ich vermutl.auch bei meiner variante über die StringUmwandlung bleiben. ...komisch ich dachte da gabs mal ne arithmetische function für.. vielleicht find ich ja noch was.
Danke auf jeden Fall für eure Hilfe
GTA-Place - Fr 15.12.06 21:43
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| uses Math;
var X: Extended; begin X := 4.000132; X := Frac(X); X := X * Power(10, Length(FloatToStr(X))) / 100; |
Gibt X = 132 aus.
[Warnung: Vorläufig und in kurzer Zeit erstelle Funktion, enthält Fehler ab bestimmter Anzahl Nachkommastellen, wird noch verbessert! Die Stringumwandlung will ich noch wegbekommen.]
herby - Fr 15.12.06 21:57
@GTA-Place:
ich hab das mal probiert mit
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function FracToInt(d: extended): integer; var X: Extended; begin X := Frac(d); X := X * Power(10, Length(FloatToStr(X))) / 100; result := Trunc(X); end;
procedure TForm1.Button1Click(Sender: TObject); begin Showmessage(IntToStr(FracToInt(24236.12348))); end; |
Da kommt bei mir bei deiner Variante -309760000 raus (statt 12348) :? :? ...hab ich da was falsch gemacht?
GTA-Place - Fr 15.12.06 22:01
Kann auch mein Fehler sein, ich probier noch bissl rum.
hansa - Fr 15.12.06 22:05
Was ist nur an den String-Funktionen so schwer ?
Die feste 10 von GTA kann man doch wunderbar eliminieren :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
uses Math;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var r, f : real; st : string; p : integer; begin st := '1,2345'; r := StrToFloat (st); f := Frac (r); p := length (st) - pos (',',st); showmessage (FloatToStr (f * power (10,p))); end;
end. |
Ob das jetzt mit 3978 Dezimalstellen funktioniert glaube ich allerdings nicht. :mrgreen:
Marc. - Fr 15.12.06 22:07
Warum so kompliziert?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function FracToInt(d: extended): integer; var X: Extended; begin X := Frac(d)*10; X := Length(FloatToStr(X))-1 ; result := Trunc(X); end; [...] begin Showmessage(IntToStr(FracToInt(24236.12345))); end; [...] |
marc
herby - Fr 15.12.06 22:17
Marc. hat folgendes geschrieben: |
Warum so kompliziert?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function FracToInt(d: extended): integer; var X: Extended; begin X := Frac(d)*10; X := Length(FloatToStr(X))-1 ; result := Trunc(X); end; [...] begin Showmessage(IntToStr(FracToInt(24236.12345))); end; [...] |
marc |
hmm.. da kommt jetzt aber bei mir 5 raus (statt 12345) - oder hast du das eher zum eruieren der kommastellen-Anzahl gedacht?
mit dem Functionsnamen FracToInt wollt ich eigentlich ausdrücken das die Function so wie der Topic sagt den Wert hinter der Kommastelle als Ganzzahl zurückgibt (nicht die Anzahl der Kommastellen)
hansa - Fr 15.12.06 22:17
Bei der Koblenzer Sache hier :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button1Click(Sender: TObject); var X: Extended; st : string; d : real; begin d := 1.0002345; X := Frac(d)*10; X := Length(FloatToStr(X))-1 ; Showmessage(FloatToStr(Trunc (x))); end; |
kommt bei mir 18 raus. :shock:
Und bei meinem Beispiel gibts Rundungsdifferenzen in der Power Zeile. Die sind so allerdings nicht mehr zu bemerken :
Delphi-Quelltext
1:
| showmessage (IntToStr (round (f * power (10,p)))); |
Vielleicht gehts auch ohne round mit anderem Zahlentyp. So, genug gespielt. :mrgreen:
GTA-Place - Fr 15.12.06 22:18
Marc: Du musst schon lesen, was er will. Da kommt 5 raus ;-).
Marc. - Fr 15.12.06 22:19
Zitat: |
...aber zuerst müsste man mal die Anzahl der Kommastellen rauskriegen. |
-> Deine Funktion abgeändert ergab meine.
Zitat: |
kommt bei mir 18 raus. :shock: |
Bei mir 7 ;). Da hast du was falsch gemacht.
herby - Fr 15.12.06 22:30
ja.. dann wärs aber wieder 2x über den sattel gezogen
zuerts marcs Funktion zum eruieren der Kommastellen. und danach müsst ich dann noch die Frac(24236.12345) welche 0.12345 ergiebt nachKommastellenMal mit 10 multiplizieren damit ich dann wieder auf die Ganzahl der Nachkommassumme komme. (naja... dann doch lieber die StringUmwandlung mit Copy ab Komma) .. ich dachte eigentlich da war mal ne arithmetische Funktion die das in einem einzigen Rutsch erledigte ...bin gerade auch noch meine "Kochbücher" am studieren ...vielleicht find ich da noch was
hansa - Fr 15.12.06 22:30
Marc. hat folgendes geschrieben: |
Bei mir 7 ;). Da hast du was falsch gemacht. |
Nene, 24236.12345 ergibt bei mir z.B. 15. Da ist keinerlei Kausalität drin zu entdecken. :lol: Das stimmt so nicht. Was ist mit meiner Funktion ? Geht die etwa nicht ?
GTA-Place - Fr 15.12.06 22:34
Delphi hat es nicht so mit rechnen (EDIT: Hier stand Schwachsinn) und umwandeln in einen String bringt auch Probleme, wegen der Darstellung 1,32E-10.
Z.B. funktioniert das hier gut:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var X: Extended; Y: Extended; begin X := 4.000132; X := Frac(X); Y := FracToInt(X); Y := Power(10, Y) * X; |
Aber mit X = 4.000
0132; schon nicht mehr.
herby - Fr 15.12.06 22:39
@hansa na ja... stimmen schon. Aber du machst ja schliesslich die Nachkommastellen-Eruierung auch über ne StringUmwandlung mit Pos (bei der jedoch der länderspezifische DecimalSeperator nicht bedacht ist.
da ists dann zu meiner "Ursprungsvriante" die dazu noch den RechtsCopy des (da nun eh schon vorhandenen ungewünschten) Strings macht nicht mehr weit. ...und wie GTA-Place schon sagte ist mir diese StringUmwandlung selber auch ein Dorn im Auge, darum such ich ja nach einer arithmetischen Variante
...hmm scheint Kowalski hat da auch nichts passendes in seinen (ansonsten perfekten) Kochbüchern :(
herby - Fr 15.12.06 23:27
auch ne veriante - danke für den Link
Nur leider gibts ab bestimmten Werten Rundungsdifferenzen :( (egal wie hoch man dann die constante ccMaxDigits dreht)
im Beispiel unten kommt zB. 12345677999999 raus statt 12345678. Die fixe Constante ist nicht unbedingt mein fall ebenso das hier auch eine Schleife durchgerattert wird (aber mit dem könnt ich jedoch noch leben)
hier mal die Function von alzaimar:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| Function ExractFractionalPart (aValue : Extended) : Int64; Const ccMaxDigits = 100000000000000; // Weiss nicht, ob das reicht Begin Result := Trunc (ccMaxDigits * Frac(aValue)); // z.b. : 1.23 => 230000000 While (Result>0) And (Result mod 10 = 0) do // Solange <>0 und die letzte Stelle 0 ist, wegschnippeln Result := Result div 10; End;
procedure TForm1.Button1Click(Sender: TObject); begin Showmessage(IntToStr(ExractFractionalPart(2456.12345678))); end; |
aber ich hab jetzt schon jede Menge Denkanstösse für bekommen - glaub dass ich mir da jetzt was zusammenschustern kann
Danke nochmal euch allen für eure Zeit
eruhenon - Fr 15.12.06 23:38
herby hat folgendes geschrieben: |
@hansa na ja... stimmen schon. Aber du machst ja schliesslich die Nachkommastellen-Eruierung auch über ne StringUmwandlung mit Pos (bei der jedoch der länderspezifische DecimalSeperator nicht bedacht ist. |
nur mal so als frage aber passt sich das dann nicht an?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var zahl:real; st:string; begin zahl:=1.067843214; st:=floattostr(zahl); delete(st,1,pos(DecimalSeparator,st)); while st[1]='0' do delete(st,1,1); label1.Caption:=st; end; |
herby - Fr 15.12.06 23:51
eruhenon hat folgendes geschrieben: |
nur mal so als frage aber passt sich das dann nicht an?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var zahl:real; st:string; begin zahl:=1.067843214; st:=floattostr(zahl); delete(st,1,pos(DecimalSeparator,st)); while st[1]='0' do delete(st,1,1); label1.Caption:=st; end; | |
doch, so schon. (weiss jetzt nicht wo dein code herkommt) Nur wenn man fix nach einem Beistrich sucht wie's in dem obigen Beispiel der Fall war
Zitat: |
length (st) - pos (',',st); |
wird man womöglich auf anderen Maschinen einfahren. Wenn jedoch die DecimalSeparator variable verwendet wird (wie in deinem Beispiel) sollte eigentlich das Dezimalzeichen auch das sein welches auf der Machine eingestellt ist.
...aber wie gesagt, ich möchte ja dieser "String-Wurschtlerei" aus dem Wege gehen. ...da gabs hier schon einige gute mathematische Ansätze aus denen ich mir sicher was bauen kann.
eruhenon - Fr 15.12.06 23:57
ich hab das nur kurz selbst geschrieben und die variable hab ich irgentwo in einem der vorherigen beiträge gesehn...
wenn ich das aber richtig sehe wird bei der mathematik allerdings immer eine gewisse tolleranz vorhanden sein.
hansa - Sa 16.12.06 02:34
eruhenon hat folgendes geschrieben: |
...wenn ich das aber richtig sehe wird bei der mathematik
allerdings immer eine gewisse tolleranz vorhanden sein. |
Du bist in dieser Richtung völlig auf dem falschen Weg. In Richtung Mathematik ist wirklich nichts zu machen. Von wegen Toleranz. Zahl ist Zahl und Basta. Rien ne va plus 8)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!