Jak zamienić liczby double na real

0

Witam.

Mam taki problem.

Potrzebuje zamieniać liczby typu double (8 bajtowe), na typ real(6 bajtowe).
Zwykłe przypisanie typu real=double działa, ale do momentu, kiedy double mieści się w zakresie real.
Inaczej mam błędy typu overflow oraz underflow.

Może ktoś zna algorytm takiej zamiany?

0

typ Real (6 bajtowy) z racji swojej budowy jest niezbyt lubiany przez procesory, i nie zaleca się jego stosowania. W jakim celu chcesz dokonać takiej zamiany, bo wydaje mi się ona bez sensu (pomijam fakt zmniejszenia zakresu zmiennej, którego raczej nie da się obejść).

0

Nie da się wlać 2 litrów wody do jendolitrowego pojemnika. Każdy typ ma określony przedział wartości i nic z tym nie zrobisz. Poza tym kompletnie nie rozumiem po co ta konwersja, mija się ona z celem. </url>

0

Potrzebne mi to jest, ponieważ przechodzimy z programu w napisanego w Pascalu, gdzie korzystaliśmy z typów typu Real, na ten sam program kompilowany w Lazarusie, gdzie trzba było przerobić wszystkie pola w bazie danych typu Real na Double.

Zaistniała jednak potrzeba, aby zapis do bazy danych odbywał się zarówno do nowych pól typu double jak i tych poprzednich typu Real.

Np.

definicja tabeli

txTabela = record
rIloscOld: Real;
sS: String;
rIlosc: Double;
end;

Niestety nie można zmienić poprzedniego pola rIlosc (teraz rIloscOld), na typ double, bo poprzestawiają się ofsety pól w tabeli.

Zapis odbywa się do pola typu Double, ale potrzebuje też tą samą liczbę zapisać do pola typu Real, żeby była zgodność z poprzednimi wersjami programu.

Wiadomo, że strace na dokładności w trakcie przepisywania Real = Double.

0

Jeżeli w całym programie możesz zmienić by dostęp do zmiennej rIloscOld odbywał się poprzez funkcje to da się to zrobić. Kiedyś zapisywałem real na chyba 3 bajtach.

0

stracisz nie tylko na dokładności. Po protstu dana liczba może zostać zapisana jako Double, ale w Real może już się nie zmieścić. I na to nic nie poradzisz. Na Twoim miejscu poważnie zastanowiłbym się nad napisaniem tego od nowa, włącznie z przekonwertowaniem istniejącej już bazy danych. Utrzymywanie tego w obecnej postaci i dalsze kombinowanie może narobić jeszcze większego bałaganu.

0

Jestem za "konwersją", choć czasem może to być kłopotliwe (trzeba liczyć się np. z ograniczeniami dysku). Zapisanie programu tak by dostęp do pól rekordu bazy odbywał się poprzez funkcje jest także dobrym zwyczajem, pozwala ukrywać właśnie takie sztuczki. Możemy np. liczby o wielkim zakresie zapisywać np. w 3 bajtach, dwubajtowa mantysa i bajt na cechę "liczba == mantysa * 10^ cecha", choć ja robiłem to jakby inaczej. Jeżeli przy zapisie pominiesz 2 pierwsze bajty zmiennej typu double, a przy odczycie uzupełnisz je nawet losową wartością, uzyskasz to co chciałeś. Zobacz np. to

 var
 t:record case integer of
   1: (d:double);
   2: (a:array[1..8] of byte);
 end;

begin
  t.d:=pi*1e200;
  t.a[1]:=0;
  t.a[2]:=0;
  writeln(pi*1e200);
  writeln(t.d);
end.

uzyskasz coś takiego:

3.1415926535897932E+0200
3.141592653550510E+200
0

Jestem w trakcie przebudowy bazy danych. Pierwszą rzeczą jaką zrobiłem było napisanie konwertora z old na new. Bez kombinowania bo prędzej czy później prawa Murphi'ego Cię dopadną i będziesz miał wówczas problem.

P.S.

Jak długo piszę programy, tak jeszcze nie przepełniłem typów zmiennoprzecinkowych (bo to o astrofizykę trąca).
Jeżeli do przesuwania w pliku używasz SizeOf, to nie będzie problemu jak przepiszesz zawartość starej bazy do nowej. Poprawki w programie nawet nie będą wymagane.

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