Delphi não sabe fazer conta?

Delphi

13/06/2005

Estou desenvolvendo um aplicativo para Km de arrancada, e tenho alguns sensores no trecho, porém ao fazer as contas para cálculo de velocidade, onde emprego milisegundos, e o delphi fornece números absurdos, vamos as contas
Tenho 2 sensores distantes a 0.5m, pego a diferença de tempo gasta para efetuar o trecho(calculando este pequeno trecho como aceleração zero) para calcular a velocidade, então tenho
Velocidade = (distanciaentresensores /(temponosensor2-temponosensor1)) * 3.6
isto forneceria a velocidade em km/h, porém quando faço a conta na calculadora ele me fornece a velocidade correta, mas quando mando o delphi calcular obtenho um número maluco.
ex: velocidade = (0.5 / 0,010) * 3.6 ->considerando a distância entre sensores de 0.5m e o tempo de 100 milésimos de segundo o que a calculadora me fornece 180km/h, porém com as mesmas contas o delphi me fornece 15552000 km/h.
Alguém sabe explicar o porquê disto?


Edilcimar

Edilcimar

Curtidas 0

Respostas

Massuda

Massuda

13/06/2005

ex: velocidade = (0.5 / 0,010) * 3.6 ->considerando a distância entre sensores de 0.5m e o tempo de 100 milésimos de segundo o que a calculadora me fornece 180km/h, porém com as mesmas contas o delphi me fornece 15552000 km/h.
100 milésimos de segundo não seriam 0.1 segundo? Nesse caso a velocidade seria 18 km/h.

Com relação ao cálculo feito pelo Delphi, teria como postar o código que você está usando (incluindo os tipos das variáveis)?


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

desculpa, erro de digitação, na realidade são 10 milésimos mesmo


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

A leitura dos sensores que não estaõ compativeis e não especificamente erro de conta ...

é claro que se colocar no delphi os valores corretos ele ira fazer a conta correta.. Porque não iria faze-lo... :?: :?: :?:

se os dois sensores não estiverem bem sincronizados , qualquer leitura errada é um desastre :cry: :cry: :cry:

Porque que voce não tarabalha com a função GetTickCount , se não me engano retorna valores ate em milisegundos

//Api do windows --->> Permite a sincronização .. Ao fim do processo podemos
//medir qual o tempo gasto na operação
  t := GetTickCount;



GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

a parte que está sendo desenvolvida ainda é da cronometragem manual, ou seja a pessoa entra com o tempo encontrado para o programa calcular, na segunda fase é que será feita a automação pois a pessoa ainda está procurando alguém para desenvolver a interface para o computador segue o código para que vc possa ver
Try
Tempo2 := EncodeTime(0,StrToInt(Copy(MaskEdit9.Text,1,2)),StrToInt(Copy(MaskEdit9.Text,4,2)),StrToInt(Copy(MaskEdit9.Text,7,3)));
Except
ShowMessage(´ESTE NÃO É UM TEMPO VÁLIDO´+#13+10+
´PREENCHA TODO O CAMPO, COM´+13+10+
´ZEROS À ESQUERDA SE NECESSÁRIO´+13+10+
´NO FORMATO ESCRITO EM VERMELHO´);
MaskEdit9.SetFocus;
End;
If TempoMeio > 0 then
Begin
VelocidadeMeio := (Sensor1 / (Tempo2 - TempoMeio)) * 3.6;
MaskEdit7.Text := FloatToStrF(VelocidadeMeio, ffFixed,5,2);
End;
este princípio é utilizado em todos maskedit onde são entrados os tempos


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

pessoa entra com o tempo encontrado para o programa calcular


e qual são os valores que a pessoa esta entrando para o tempo2 e o tempoMeio e velocidademeio
e como esta a msacara do maskedits

e como voce definiu o tipo dessas variáveis

so para fazer um teste aqui


GOSTEI 0
Massuda

Massuda

13/06/2005

...Tempo2 := EncodeTime(...
O valor retornado por EncodeTime [b:a55e88689e]não[/b:a55e88689e] está em segundos ou milissegundos, esse valor está em dias.

Para um valor de 10 ms, EncodeTime retorna algo como 1,5x10e-7.

Para obter o tempo em segundos, multiplique o resultado de EncodeTime por 24*60*60.


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

O valor retornado por EncodeTime não está em segundos ou milissegundos, esse valor está em dias.


o valor retornado por EncodeTime é um TTime.. Porque voce disse quu que esta em dias , se le não passa de 1

so quando

var
 Valor:TTime; 
begin
Valor:=encodeTime(23,59,59,59);
showmessage(FloatToStr(valor));end; //ou
showmessage(timeToStr(valor));end;
//ou

Ele se aproxima de 1....


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

É realmente como é um TTime deveria retornar hora, uma vez que eu mando hora, minuto, segundo e milisegundo, porém o massuda está certo, ele retorna em dias, após raciocinar sobre dias e refazer as contas ele funcionou correto


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

ele retorna em dias,


pode ate ter dado certo... mas que retorna em dias.. HA , isto eu to duvidando.. :cry: :cry: :cry: :cry:

[b:9c93b1a633]Com eu disse anteriromente , o valor não passa de um...[/b:9c93b1a633]

tanto que não retorna em dias , que se testar o codigo abaixo:

var
 Tempo:TTime;
begin
 Tempo:=EncodeTime(23,59,59,59);
 showmessage(FloatToStr(tempo));
 showmessage(TimeToStr(tempo));
 showmessage(DateTimeToStr(tempo));
end;


:arrow: sera a velha e conhecida data 30/12/1899...

eu acho , que o problema estava na sua conta , onde voce teria que fazer a conta levando em conta so o milesegundo , voce levava em conta a Hora toda....


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

Marcos eu concordo contigo, mas o que acontece é que apesar de eu ter utilizado encodetime e não incodedatetime o delphi está dando o resultado em dias e não em hh:mm:ss:zzz, coloque um maskedit com máscara com este formato e teste.


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

Eu quero testar.. Foi isso mesmo que lhe pedi anteriormente e voce não forneceu :cry: :cry: :cry:

Código: pessoa entra com o tempo encontrado para o programa calcular e qual são os valores que a pessoa esta entrando para o tempo2 e o tempoMeio e velocidademeio e como esta a msacara do maskedits e como voce definiu o tipo dessas variáveis so para fazer um teste aqui



GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

mas o código já está logo ali em cima, é só testar, a única coisa que tem que fazer é colocar 2 maskedit com máscara hh:mm:ss:zzz, sendo que o segundo terá um valor um pouquinho maior que o primeiro, os dados que estou utilizando são distancia entre as tomadas de tempo 0.50m e uma diferença de tempo de 0.010s


GOSTEI 0
Massuda

Massuda

13/06/2005

[quote:614acece57=´Marco Salles´]o valor retornado por EncodeTime é um TTime.. Porque voce disse quu que esta em dias....[/quote:614acece57]Segundo a Ajuda do Delphi, [url=http://www.delphibasics.co.uk/RTL.asp?Name=EncodeTime]EncodeTime[/url] retorna um TDateTime.

A interpretação do TDateTime depende do que está medindo... se for uma data, é o total de dias decorridos desde 30/12/1899 12:00:00.

Se você quiser encarar de outra forma, pode pensar que o valor retornado por EncodeTime é a hora expressa como sendo uma fração de um dia.


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

massuda, se eu tenho uma fração do dia então a diferença entre duas frações do dia continua a chegando aos milisengundos, o que deveria fazer com que a minha conta desse certo, mas no entanto não dá, só dá com a transformação que vc falou!


GOSTEI 0
Massuda

Massuda

13/06/2005

se eu tenho uma fração do dia então a diferença entre duas frações do dia continua a chegando aos milisengundos, o que deveria fazer com que a minha conta desse certo, mas no entanto não dá...
Não... a diferença continuará dando fração de dia. Se você tem 0.5 dia (12h) e subtrair 0.25 dia (6h) dá 0.25 dia (6h) e não 0.25 ms.

...só dá com a transformação que vc falou!
A conversão que eu falei converte de fração de dia para segundos. Note que 24*60*60 é o total de segundos em um dia.


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

certo massuda se eu tenho 0.5 do dia menos 0,25 do dia terei como resultado 0,25 do dia que equivale a 6 h. como na minha diferença de tempo eu tenho 0.010s isto vai me dar uma fração do dia bem pequena(como vc disse antes aprox. ,5x10e-7), que na hora de fazer as contas deveria equivaler aos mesmos 0.010s, mas o fato é que isto não está dando certo, se eu tenho que multiplicar este resultado por 86400 (quantidade de segundos em um dia) é porque o encode está de devolvendo um número ainda menor


GOSTEI 0
Massuda

Massuda

13/06/2005

...como na minha diferença de tempo eu tenho 0.010s isto vai me dar uma fração do dia bem pequena
Sua diferença de tempo...
Tempo2 - TempoMeio
...foi obtida a partir de valores retornados por EncodeTime? nesse caso, os dois valores são frações de dia e a diferença, consequentemente, será uma fração de dia.

Quando você multiplica por 86400 o resultado do EncodeTime, Tempo2 e TempoMeio passam a ser tempos em segundos.


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

correto, isto prova que ele não está me fornecendo segundo ou milisegundo, ele está me fornecendo uma fração do dia(ou seja lá o que for) equivalente a 1/86400 s. e no help do encodetime diz que o padrao dele é 1/1000s(os 3 zes), então voltamos ao início se eu tenho uma fração de dia equivalente a um tempo e outra fração de dia equivalente a outro tempo onde a diferença entre estes tempos é 0.010s., não importa em que unidade ele está me fornecendo esta fração ele teria que ser ou em dias, horas, minutos, segundos ou milisegundos, mas com uma diferença de 10 qualquer coisa entre elas, porém se preciso multiplicar por uma número maior que 1000 então ele está fugindo do próprio padrão do encode que é milésimos de segundo!


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

Pera ai....

volto ja


GOSTEI 0
Massuda

Massuda

13/06/2005

...no help do encodetime diz que o padrao dele é 1/1000s(os 3 zes)...
Na Ajuda do Delphi que estou usando (D5), consta...
The resulting value is a number between 0 (inclusive) and 1 (not inclusive) that indicates the fractional part of a day given by the specified time. The value 0 corresponds to midnight, 0.5 corresponds to noon, 0.75 corresponds to 6:00 pm, and so on.
...ou seja, que o valor resultante é a fração do dia correspondente ao horário especificado. Qual a versão do seu Delphi?


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

help do d7
Returns a TDateTime value for a specified Hour, Min, Sec, and MSec.
Unit
SysUtils
Category
datetime routines
Delphi syntax:

function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;

C++ syntax:
extern PACKAGE System::TDateTime __fastcall EncodeTime(Word Hour, Word Min, Word Sec, Word MSec);

Description

EncodeTime encodes the given hour, minute, second, and millisecond into a TDateTime value.

Valid Hour values are 0 through 23.

Valid Min and Sec values are 0 through 59.

Valid MSec values are 0 through [b:6eca7e8f11]999[/b:6eca7e8f11]. [u:6eca7e8f11][b:6eca7e8f11]Aqui[/b:6eca7e8f11][/u:6eca7e8f11]

If the specified values are not within range, EncodeTime raises an EConvertError exception.

The resulting value is a number between 0 and 1 (inclusive) that indicates the fractional part of a day given by the specified time or (if 1.0) midnight on the following day. The value 0 corresponds to midnight, 0.5 corresponds to noon, 0.75 corresponds to 6:00 pm, and so on.


GOSTEI 0
Massuda

Massuda

13/06/2005

Valid MSec values are 0 through [b:c0dfb33489]999[/b:c0dfb33489]. [u:c0dfb33489][b:c0dfb33489]Aqui[/b:c0dfb33489][/u:c0dfb33489]
Isso significa que os valores válidos para MSec (milissegundos) vão de 0 a 999... não implica que o retorno da função seja em milissegundos.


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

Pera ai....

cheguei:

senhores , a função [b:e0a20b1b09]encodetime[/b:e0a20b1b09] retorna un numero de ponto flutuante..

Vou tentar expor aquilo quer acho que sei sobre esta função

nada melhor que um exemplo:

var
 horario:TTime;
begin
 horario:=encodeTime(12,10,20,30);
 showmessage(FloatTostr(horario));
end
;

[b:e0a20b1b09]ele retorna o numero 0,507176273148148[/b:e0a20b1b09]

como o compilador , obetem esse numero ???

a conta é

(12*60*60*1000 + 10*60*1000 + 20*1000 + 30)/(24*60*60*1000)

esta é a conta que o compilador , faz para representar este numero em ponto flutuante... É mais fácil somar numeros de pontos flutuantes do que
horas... Por isso é conveniente eçle trabalhar assim

é claro que há uma equivalencia unica entre o numero de ponto flutuante e a hora.. Logo dado o numero 0,507176273148148 , o compilador deve ser capaz de retornar a hora 12:10:20:40

O Processo inverso pode ser obtido atrvés de um algoritimo simples com o que segue abaixo:

1) Multiplicamos  0,507176273148148  por 24*60*60*1000 

2) obtemos o numero = 43820029,9999 

3) Truncamos e arredondamos -->>> Ficando assim: 43820030

4)calcuo da hora
   hora:= 43820030 div 60*60*1000 = 12
   resto:=43820030 mod 60*60*1000 = 620030

5)calculo do minuto
   minuto = 620030 div 60*1000 = 10
   resto   = 620030 mod 60*1000 = 20030

6) calculo do segundo
   segundo = 20030 div 1000 = 20
   resto:= 20030 mod 1000 

7)calculo do msegundo
   msecundo =resto = 30


apresentei isto apenas como detalhes , para reforçar a idéia que o numero retornado pela função encodetime é un numero de ponto flutuante, que pode ser determinado

[b:e0a20b1b09]o problema no meu entendimento , não é que o valor retornado pelo encodetime esta em dias ... O Fato é que é simplesmente un numero de ponto flutuante[/b:e0a20b1b09]

para esclarecer as coisas vamos a um exemplo

horario=strtotime(12:00:00) // em ponto flutuante = 0,5

ora se o carro gasta 12 horas para andar 120 km é claro que a velocidade do carro é v=120/12 = 10km/h Mas o compilador não entende assim... ele entende assim v=12/0,5 = 24km/h


[b:e0a20b1b09]Hora , então ele não sabe fazer conta[/b:e0a20b1b09] :?: :?: :?: :?:

:arrow:
[b:e0a20b1b09]sabe , o problema é que a base de dados tem que estar certa...[/b:e0a20b1b09]

[b:e0a20b1b09]Outro conceito fundamental neste processo é que não so devemos retornar a base de dados para o formato de horas , com devemos fazer uma transformação de hh:mm:s:ms em um numero decimal[/b:e0a20b1b09]

No ultimo exemplo é claro que 12:00:00:00 = 12 decimal ..sera indiferente


vistos esses mau entendidos , eu não sei se os senhores estão concordando , mas segue abaixo um exemplo de conversão, que o edicilmar pode ter uma idéia de como proceder no seu caso particular

procedure TForm1.Button1Click(Sender: TObject);
var
 t1,t2:TTime;
 distancia:Real;
 velocidade:Real;
 diferenca:TTime;
 h,m,s,ms:Word;
 numero:Real;
begin
//neste exemplo , fiz um intervalo de tempoigual a 0,1segundo = 100ms
 t1:=Encodetime(01,10,20,000); //tempo de saida
 t2:=encodetime(01,10,20,100); // T2 ... tempo de chegada
 distancia:=0.5;
 diferenca:=T2-t1; //é a diferença que  carro leva para percorrer
 decodeTime(diferenca,h,m,s,ms);
//represental  o decimal da hora
numero:=(h*60*60*1000 + m*60*1000 + s*1000 + ms);
//não dividir agora por 1000*60*60; senão nunero ficaria muito pequeno 
 velocidade:=(distancia/numero)*3600;
 showmessage(floattostr(velocidade));
end;


P;s *********************************************************
o correto seria
numero:=(h*60*60*1000 + m*60*1000 + s*1000 + ms)/1000*60*60;
velocidade:=(distancia/numero)/1000;

substitui por :

numero:=(h*60*60*1000 + m*60*1000 + s*1000 + ms);
velocidade:=(distancia/numero)*3600;

[b:e0a20b1b09]que é a mesma coisa[/b:e0a20b1b09], não faz diferença.. so mesmo para evitar numeros muito pequenos :wink:

*************************************************************

Conclusão...O erro  não é o que  função encodetime retorna , mas sim  como  utilizalar o valor de retorno desta função



GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

Muito boa a explicação marcos, só que cheguei num impasse, se colocar a distância grande entre sensores não poderei desprezar a aceleração existente pois o veículo está acelerando o tempo todo(numa distância pequena como 0.5m ou até mesmo 1m dá para desconsiderar a aceleração sofrida), porém na última tomada de velocidade(final da pista) o carro, dependendo da categoria, já está com uma velocidade bem acima de 200km/h, e aí o milisegundo é uma fração grande para uma precisão, então eu teria que considerar o décimo de milésimo do segundo(0.0001s) e aí o encode não funciona mais(eu já tentei) e eu não posso colocar ponto flutuante para o usuário transformar o tempo em ponto flutuante. Você tem alguma idéia de como acrescentar estes décimos de milésimos de modo que ficasse transparente para o usuário? A formatação da máscara deveria ficar hh:mm:ss:zzzz, existinto a quarta casa


GOSTEI 0
Massuda

Massuda

13/06/2005

...alguma idéia de como acrescentar estes décimos de milésimos de modo que ficasse transparente para o usuário? A formatação da máscara deveria ficar hh:mm:ss:zzzz, existinto a quarta casa
Minha sugestão seria que você deixasse de usar um TDateTime para armazenar os tempos e passasse a usar um Currency para armazenar esses valores em segundos (com precisão de 4 casas decimais). Nesse caso você teria que fazer uma função para converter o texto informado pelo usuário para segundos, mas isso não é complicado.


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

Minha sugestão seria que você deixasse de usar um TDateTime para armazenar os tempos e passasse a usar um Currency para armazenar esses valores


Acho que a idéia é esta...Uma vez fiz algo parecido.. So que trabalhei com String...E Criei as funçoes correspondentes ..

No caso do edicilmar , teste e verifique possíveis erros.. É so uma idéia

function TransformaHoraEmPontoFlutuante(texto:string):Real;
var
 h,mm,ss,ms:Word;
 fator:Integer;
begin
 fator:=36000000;
 h:=strtoint(copy(texto,1,2));
 mm:=strtoint(copy(texto,3,2));
 ss:=strtoint(copy(texto,5,2));
 ms:=strtoint(copy(texto,7,4));
 result:=((h*fator)+(mm*(fator/60))+(ss*(fator/(60*60)))+ms)/(24*fator);
end;


//Função abiaxo , funciona com se fosse um decodetima
function TransformarPontoFlutuanteTexto(pontoflutuante:Real;var h,mm,ss,ms:Word):String;
var
//h,mm,ss,ms:Word;
resto:Integer;
fator:Integer;
fracao:Integer;
begin
 fator:=864000000;
 fracao:=Round(pontoflutuante*fator);
 fator:=Fator div 24;
 h:=Fracao div fator;
 resto:=Fracao mod fator;
 fator:=fator div 60;
 mm:=Resto div fator;
 resto:= Resto mod fator;
 fator:=fator div 60;
 ss:= resto div fator;
 ms:= resto mod fator;
 result:=inttostr(h)+´:´+inttostr(mm)+´:´+inttostr(ss)+´:´+inttostr(ms);
//melhorar por exemplo esta formatação
end;


Vamos aos calculos práticos

Exemplo de um carro que percorre 0,5 m no tempo de 0,1 decimo de melisegundo... Eta carro veloz :lol: :lol: :lol:

procedure TForm1.Button2Click(Sender: TObject);
var
 t1,t2:real;
 distancia:Real;
 velocidade:Real;
 diferenca:real;
 h,mm,ss,ms:Word;
 numero:Real;
begin
//neste exemplo , fiz um intervalo de tempoigual a 0,0001 segundo = 0,1ms
 t1:=TransformaHoraEmPontoFlutuante(´0110200000´); //tempo de saida
 t2:=TransformaHoraEmPontoFlutuante(´0110200001´); // T2 ... tempo de chegada
 distancia:=0.5;
 diferenca:=T2-t1; //é a diferença que  carro leva para percorrer
 TransformarPontoFlutuanteTexto(diferenca,h,mm,ss,ms);
numero:=(h*60*60*10000 + mm*60*10000 + ss*10000 + ms);
//não dividir agora por 10000*60*60; senão nunero ficaria muito pequeno
 velocidade:=(distancia/numero)*36000;
 showmessage(floattostr(velocidade));
end;


ve se dá para ter uma idéia...


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

vou testar depois aviso, quanto ao carro veloz não é que ele percorra 1/2 metro em 0,0001s, mas para marcar a diferença entre os carros e para calcular a velocidade com mais precisão, suponha que um leve 0,0012 e outro leve 0,0015, aí dá para entender


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

valeu, a tranformação em ponto flutuante funcionou e calculou a velocidade corretamente, falta testar a transformação de flutuante para hora, depois que testar informo
procedure TForm6.MaskEdit4Exit(Sender: TObject);
begin
MaskEdit4.Color := $00FFFFFF;
Try
TempoMeio := 86400 * TransformaHoraEmPontoFlutuante(MaskEdit4.Text);
Except
ShowMessage(´ESTE NÃO É UM TEMPO VÁLIDO´+#13+10+
´PREENCHA TODO O CAMPO, COM´+13+10+
´ZEROS À ESQUERDA SE NECESSÁRIO´+13+10+
´NO FORMATO ESCRITO EM VERMELHO´);
MaskEdit4.SetFocus;
End;
If Tempo2 > 0 then
Begin
VelocidadeMeio := (Sensor1 / (Tempo2 - TempoMeio)) * 3.6;
MaskEdit7.Text := FloatToStrF(VelocidadeMeio, ffFixed,5,2);
End;
end;


GOSTEI 0
Marco Salles

Marco Salles

13/06/2005

quanto ao carro veloz não é que ele percorra 1/2 metro em 0,0001s, mas para marcar a diferença entre os carros e para calcular a velocidade com mais precisão, suponha que um leve 0,0012 e outro leve 0,0015, aí dá para entender


eu tava brincando... Ja tinha entendido

falta testar a transformação de flutuante


procedure TForm1.Button1Click(Sender: TObject);
var
 h,mm,ss,ms:Word;
begin
edit1.text:=
TransformarPontoFlutuanteTexto(TransformaHoraEmPontoFlutuante(´1210203040´),h,mm,ss,ms);
end;


sem probleam

No fim acho so que voce deve se preocupar em formatar , restringir os valores de entrada e saidas válidos...

A Vantagem dessse tipo de transformação é que na função encodeTime as entradas
Time:=(25,10,20,30) Da erro pois 25 não é um valor válido para Hora...
Ja trabalhando com String Poderemos ter Horas como o formato de
25:10:20:30 , isto apesar de não ser usual em termos de parametros de medir tempo, tem serventia quando se trata de acumular horas (Como um Banco de Horas Por exemplo).. Sei que este não é o seu caso , mas fica aqui , levantado esta possibilidade.


GOSTEI 0
Edilcimar

Edilcimar

13/06/2005

a função ransformarPontoFlutuanteTexto funcionou com adaptação, só que tive que trocar o tipo de campo do banco de dados de time para numérico para poder guardar este valor fracionário do tempo


GOSTEI 0
POSTAR