Nella trasformazione della parte frazionale di un numero in stringa Lazarus opera di fantasia o sbaglio qualcosa?
Provate ad inserire un pulsate in una form e scrivete questo codice:
procedure TForm1.Button7Click(Sender: TObject);
var
st : string;
num : real;
mNumber : double;
begin
mNumber:= 80237,68;
num:=Frac(mNumber);
St:= IntToStr(Trunc(Num * 100));
showmessage(st);
end;
il risultato mi da 67 e non 68
Sono stupito ed un po anche inc...
con questa conversione il risultato è corretto, ciao
showmessage(FloatToStrF(num * 100, ffNumber, 10,2));
Brunello, ringrazio per la risposta.
funziona ma a me va bene così:
showmessage(FloatToStrF(num * 100, ffNumber, 10,0));
perchè non voglio decimali di decimali.
Avevo già risolto con:
st:=rightstr(Floattostr(mNumber),2);
showmessage(st);
Posso mettere risolto anche se le soluzioni trovate aggirano il problema.
...
num:=Frac(mNumber);
St:= IntToStr(Trunc(Num * 100));
showmessage(st);
end;
..
il risultato mi da 67 e non 68
Sono stupito ed un po anche inc...
Il problema non è di FP.
Probabilmente ti sfugge che i numeri sono trattati internamente in binario, non in decimale
Non puoi pensare che i numeri reali siano esattamente ciò che scrivi nel programma, specie quando hanno una parte frazionaria
Infatti quando scrivi come double il numero 80237.68 in realtà viene memorizzato internamente
80237.679999999993
Per chi è curioso:
0100000011110011100101101101101011100001010001111010111000010100
L'uso del Trunc() invece del Round() fa il resto
Te ne puoi rendere conto seguendo i passaggi uno ad uno
mNumber:= 80237.68;
num:=Frac(mNumber);
st := format('%.10f',[num]);
showmessage(st);
st := format('%.10f',[num*100]);
showmessage(st);
St:= IntToStr(Trunc(Num * 100));
showmessage(st);
Ringrazio SB e DragoRosso per avermi rinfrescato alcune nozioni. Mi occupo da oltre 30 anni di gestionali e fortunatamente ancora oggi non soffro di un galoppante "analfabetismo di ritorno".
È praticamente impossibile un dialogo sereno fra informatici puri ed un semplice ingegnere civile quasi del tutto autodidatta in informatica che cerca le procedure e funzioni di sistema per ottenere i risultati che gli interessano cercando di non complicarsi la vita. Per esperienza la precisione che viene richiesta non va oltre i quatro decimali e quindi se ho 15 o 7 cifre posso dire che ne ho fin troppe e sono costretto ad arrotondare.
Posso andare oltre e superare quanto finora discusso con questo semplice codice:
uses fpexprpars, symbolic, math;
var
s, st:string;
mNum, mNumber : real;
begin
s:='( ( 9.20*6.25 ) +9.20 *( 1.37/2 ) ) *2+ ( 10.00*6.25*2 )+( 1.00*1.35 )';
mNumber:= RoundTo(quickevaluate(s,[],[]),-2);
mNum:=Frac(mNumber);
St:= IntToStr(Trunc(mNum * 100));
showmessage(st);
//mi darà la stringa '95' che è quello che volevo
end;
il risultato real di -s- lo posso ottenere anche con una query:
ZQuery1.SQL.Text := 'SELECT ' + s+'*1.00' +';';
zQuery1.Active := True;
s:= StringReplace(zQuery1.Fields[0].Text, '.',',', [rfReplaceAll]);
mNumber:= RoundTo(StrToFloat(s),-2);
St:= IntToStr(Trunc(mNum * 100));
showmessage(st);
il segreto è RoundTo() in entrambi i casi.