Array
(
)

Problema na conversão de texto para float

Rodolfo.pirolo
   - 25 fev 2006

Estou com o seguinte problema:

O usuário irá digitar em um campo edit uma série de valores para calcular um determinado desconto acumulado. Exemplo:
edit1.text := ´20+1,5´ o resultador deve aparecer em um outro campo edit.
edt2.text := ´21´

O que não estou conseguindo fazer é pegar a string ´1,5´ e converter em uma variavel float, pois estes numeros podem ser decimais.

A variavel que receberá o valor, defini como currency. Estou transformando o texto através da função strtocurr(), e me retorna o seguinte mensagem: ´´1.5´ is not a valid floating point value´. Antes de fazer a conversão, substituo a ´,´ (virgula) pelo ´.´ (ponto).

Onde está o erro?


Aroldo Zanela
   - 26 fev 2006

Colega,

No caso, você está querendo resolver uma fórmula. Certo? Então, acredito que esta [url=http://forum.devmedia.com.br/viewtopic.php?t=73269&highlight=formula&sid=f0be5a0fa515701209f5bd9d2c014327]thread[/url] poderá ajudá-lo.


Rodolfo.pirolo
   - 26 fev 2006

Aroldo,

Eu não estou conseguindo transformar a string ´1,5´ que converti para ´1.5´ em um tipo de numero( currency, single).

Toda vez que uso as funcoes strtocurr ou strtofloat o Delphi da a mensagem de erro dizendo que ´1.5 não é um valor de ponto flutuante válido´.

Como posso converter a string ´1.5´ no número 1.5, para poder efetuar os cálculos?


Aroldo Zanela
   - 26 fev 2006

Colega,

Mantenha a vírgula na string, ou seja, não substitua por ponto.


Rodolfo.pirolo
   - 26 fev 2006

Aroldo,

Não funcionou, estou enviando parte do código, para melhorar nossa discussão. O valor de lr_Perc não é alterado, fica sempre em zero.

Onde estou errando?

Obrigado pela paciencia.

Somente para lembrar, este campo receberá valores assim ´1,5+2,5+3,5+10´.

Parte de código com problema:

procedure TformCadastroDesconto.ed_DescricaoExit(Sender: TObject);
var
li_Pos, li_TotCaract, i : integer;
ls_Texto, ls_Perc : String;
lr_valori, lr_valorf : real;
lr_Perc : single;

begin
inherited;
ls_Texto := trim( ed_descricao.text );
i := 1;
li_Pos := 1;

while i <= length( ls_Texto ) do
begin
If Copy( ls_texto, i, 1) = ´+´ then
begin
ls_Perc := Copy( ls_texto, li_Pos, i - li_Pos);
// ls_perc := stringreplace(ls_perc, ´,´ , ´.´, [rfReplaceAll]);
lr_Perc := StrToFloat( ls_perc );

li_pos := i + 1;
end;
i := i + 1;
end;
end;


Aroldo Zanela
   - 27 fev 2006

Colega,

Assim não funciona mesmo, pois o delphi não efetua interpretação de fórmulas assim. Portanto, voltamos a minha primeira resposta nesta thread, ou seja, será necessário utilizar algum componente de terceiro para implementar isso no seu sistema, ou ainda, montar um algoritmo para decomposição e cálculo da expressão.


Aroldo Zanela
   - 27 fev 2006

Colega,

hehehehehehe Desculpe, acordei agora e nem li direito o seu tópico. Agora vi que já fez o ´referido´ algoritmo. Vou olhar com calma e ver se posso ajudar.


Aroldo Zanela
   - 27 fev 2006

Colega,

Criei uma classe denominada de TFormula para implementar essa rotina:
#Código


TFormula = class(TObject)
private
FFormula: String;
FResultado: String;
procedure SetFormula(const Value: String);
public
property Formula: String read FFormula write SetFormula;
property Resultado: String read FResultado;
function ParseInput(LineData: string): Boolean;
end;


Para validar se a entrada está correta (dentro do que se espera) temos a implementação da função ParseInput:
#Código

{ TFormula }

function TFormula.ParseInput(LineData: string): Boolean;
var ValidChars: set of Char;
I, N: SmallInt;
begin
ValidChars := [´0´,´1´,´2´,´3´,´4´,´5´,´6´,´7´,´8´,´9´,´,´,´+´];
N := Length(LineData);
Result:= True;
for I := 1 to N do
begin
if not (LineData[I] in ValidChars) then
begin
Result := False;
Break;
end;
end;
end;


Na procedure SetFormula, fazemos a implementação para obtenção do resultado:
#Código

procedure TFormula.SetFormula(const Value: String);
var I, iPos, iLength: Integer;
ClearLine: string;
xValue: Double;// Valor numérico
sValue: string;// Parte da formula com um valor "válido"

begin

FFormula := Value; // "Setar valor ao atributo"
ClearLine := Value; // Atribuir o valor de entrada a variável "Linha limpa"

{Verificar se a entrada contém apenas caracteres válidos}

if ParseInput(Value) then
begin
iLength := Length(Value); // Pega o comprimento da linha
iPos := Pos(´+´, ClearLine);
xValue:= 0;
while iPos>0 do
begin
sValue := Copy(ClearLine,1,iPos-1);
xValue := xValue + StrToFloat(sValue);
ClearLine:= Copy(ClearLine, iPos+1, iLength);
iPos := Pos(´+´, ClearLine);
end;
if Length(ClearLine)>0 then
begin
xValue:= xValue + StrToFloat(ClearLine);
end;

FResultado := FloatToStr(xValue);
end else
FResultado := ´Entrada inválida.´;
end;


Finalmente, para testar, codificamos a seguintes instruções no manipulador de eventos OnClick de um botão:
#Código

procedure TForm1.btnCALCULARClick(Sender: TObject);
var Formula: TFormula;
begin
Formula:= TFormula.Create;

Formula.Formula:= edtFORMULA.Text;
edtRESULTADO.Text:= Formula.Resultado;

Formula.Free;
end;


Ah! sim, tem como fazer mais simples, mas hoje é feriado... :-)


Rodolfo.pirolo
   - 27 fev 2006

Aroldo,

Foi muito mais do que eu queria, voce deu uma verdadeira aula. Baseado nos seus exemplos encontrei onde estava a falha no meu cálculo.

Vou estudar a sua rotina com atenção.

Valeu pela ótima explicação.

Muito obrigado,

Bom final de carnaval.

Abraços

Rodolfo