Część ułamkowa jako INTEGER

0

Cześć, mam double'a w postaci X.Y. Chcę pobrać jego część ułamkową, czyli Y, a nie 0.Y(jak mi zwróci funkcja FRAC).

Więc wpadłem na super pomysł przesunięć bitowych. Jednak kompilator mnie przechytrzył i powiedział: "Operator not applicable to this operand type". Więc zacząłem grzebać w helpie. Tam znalazłem informacje(odnośnie operatorów shl i shr): "Both expressions must be absolute immediate values, and the result is an absolute immediate value." Jednak w żaden sposób nie mogę rozkminić, co to jest "immediate value" i dlaczego mój kod nie działa. Od razu mówię, że nie wiem, ile mam cyfr po przecinku. Wiem tyle, że nie więcej niż 3. I chcę to robić bez operacji na stringach.

Mój kod wygląda tak:

 
var
  verD: double;
  verMaj: integer;
  verMin: integer;
begin
  verD:=3.95; 
  VerMaj:=Trunc(verD);
  VerMin:=verD shr 1; //<- tu mam błąd
end;

To jest kod testowy(dlatego shr 1). Dlaczego nie mogę wykonać takiego przesunięcia? A może ktoś z Was już takie rzeczy robił. Tylko interesuje mnie szybkość, nie chcę tego robić na stringach.

0

hmm... wytlumacz mi jedna rzecz:
masz 3.95 i chcesz dostac samo "95", tak?
Frac() odpada bo zwroci "0.95"?
a co jesli bedziesz mial "3.095"?

0

dla mnie to też jest zagadka :)

0
var
  verD: double;
  verMaj: integer;
  verMin: integer;
begin
  verD:=3.95; 
  VerMaj:=Trunc(verD);
  VerMin:=Trunc(Frac(verD) * 1000);
end;
0
Misiekd napisał(a)
var
  verD: double;
  verMaj: integer;
  verMin: integer;
begin
  verD:=3.95; 
  VerMaj:=Trunc(verD);
  VerMin:=Trunc(Frac(verD) * 1000);
end;

Efektem tego jest 950.

0

ale 3.95 to jest to samo co 3.950 ale już 95 <> 950!
tak samo jak 3.95 <> 3.095 ale 95 = 095!
Więc może najpierw napisz proste założenia a potem być może ktoś ci wymyśli.

BTW inaczej niż stringiem na 99,99% tego nie zrobisz

0

Ja bym zaczął tak:

procedure TForm1.Button1Click(Sender: TObject);
var
  C: currency;
  D: Integer;
begin
  C := 23.95;
  C := Frac(C);
  showmessage(inttostr((PInt64(@C)^)));
end;

Pokombinuj i może sie uda

0

Misiek, ale ja nie mam 3.950, tylko mogę mieć 3.95, 3.9, 3.958. Napisałem w pierwszym poście, że jedyne co wiem to to, że nie będzie więcej niż 3 cyfry po przecinku.

A co do wersji ze wskaźnikami, nie za bardzo rozumiem.

0
Juhas napisał(a)

Misiek, ale ja nie mam 3.950, tylko mogę mieć 3.95, 3.9, 3.958. Napisałem w pierwszym poście, że jedyne co wiem to to, że nie będzie więcej niż 3 cyfry po przecinku.

A co do wersji ze wskaźnikami, nie za bardzo rozumiem.

ale wciaz nie wiemy jakiego wyniku oczekujesz po 3.095 ?

0
cimak napisał(a)
Juhas napisał(a)

Misiek, ale ja nie mam 3.950, tylko mogę mieć 3.95, 3.9, 3.958. Napisałem w pierwszym poście, że jedyne co wiem to to, że nie będzie więcej niż 3 cyfry po przecinku.

A co do wersji ze wskaźnikami, nie za bardzo rozumiem.

ale wciaz nie wiemy jakiego wyniku oczekujesz po 3.095 ?

Aha, 95 oczywiście :)
Ściślej, chcę dostać całkowitą liczbę z części ułamkowej, czyli z X.ABC, chcę dostać ABC

0

Moim sposobem zawsze uzyskasz Int'a 4 cyfrowego (z ew. dopełnieniem zer na końcu).
Pętla od 1 do 4 i operacją ANDową wyklucz zera i ew. podzielić wynik przez 10. Tak mi się wydaję.

0
Juhas napisał(a)

Ściślej, chcę dostać całkowitą liczbę z części ułamkowej, czyli z X.ABC, chcę dostać ABC

czyli dla 3.95 A = 9, B = 5, C = 0, więc 950.
dla 3.095 A = 0, B = 9, C = 5, więc 095, więc 95.
tylko tak ma to dla mnie sens i kod to robiący podał Misiek. w przeciwnym wypadku reszta(3.95) == reszta (3.095) i zrób to sobie na - blah - stringu.

0

A nie lepiej tak

Liczba := FloatToStr(3.1511);
Delete(Liczba, 1,  Pos(Liczba, '.'));
0

OK, zrobiłem po prostu na stringu za pomocą copy. W każdym razie już tak trochę z boku, czy da się to zrobić za pomocą asma? Nigdy nic w tym nie robiłem, a chciałem się zawsze nauczyć jakiś podstaw chociaż. Może to byłoby dobre zadanie na początek? ;> Da się, czy nie? Ktoś mi na to może odpowiedzieć z całą pewnością?

0

Dla tych co nie wykombinowali ;)

Function FracToInt(f:extended):Int64;
var
  i:Int64;
  tmp: extended;
begin
  i:= 1;
  tmp:= f;
  while (f <> Trunc(f)) do
  Begin
    f:= f*10;
    i:= i*10;
  End;
  Result:=round(tmp*i) mod i;
end;
0

na stringach :D

Function FracToInt(f:extended):Int64;
begin
  Result:= StrToInt(Copy(FloatToStr(f),AnsiPos(',',FloatToStr(f))+1,Length(FloatToStr(f))));
end;
0

pomnóż przez 1000 i zaokrąglij wynik....
liczbacalkowita := Trunc(Frac(liczbazmiennoprzecinkowa) * 1000 + 0.5);

1 użytkowników online, w tym zalogowanych: 0, gości: 1