Moduł OUX/C+ do obsługi dużych liczb jakby zmiennoprzecinkowych

0

Napisałem moduł OUX/C+ do obsługi dużych liczb, który znajduje się pod adresem
https://github.com/overcq/oux/blob/master/module/base/math_bignum.cx
Jest to wersja beta.
Do użycia trzeba pobrać całe środowisko OUX/C+: https://github.com/overcq/oux

Zaimplementowałem obsługę dużych liczb zmiennoprzecinkowych z wszystkimi ich wadami niedokładności. Jeśli użyć tylko liczb całkowitych, to obliczenia są przeprowadzane z pełną dokładnością. Natomiast jeśli użyć liczb ułamka dziesiętnego, to wynik jest zapisywany w dostępnej postaci ułamka dwójkowego o pewnej precyzji trochę większej niż ten ułamek.
Liczba jest przechowywana w postaci binarnej i obliczenia też są przeprowadzane na tej postaci, więc szybciej się nie da.
Obecnie dostępne są operacje: dodawania, odejmowania, negacji, mnożenia, dzielenia z modulo.
Wykonuje się na procesorach z rodziny “x86” i “x86_64”. Dla tych procesorów zostało zaimplementowane dodawanie, odejmowanie (i oparta na nim negacja) oraz mnożenie. Ale można oczywiście dopisać kod dla innych procesorów. Dzielenie z modulo jest bez wstawek asemblera w C. Dzielenie można przeprowadzać na dzielniku o dowolnej wielkości.

Tylko jak przetestować poprawność obliczeń na dużych liczbach? I dodatkowo uwzględniając niedokładność liczby zmiennoprzecinkowej.

0

Tylko jak przetestować poprawność obliczeń na dużych liczbach? I dodatkowo uwzględniając niedokładność liczby zmiennoprzecinkowej

Spróbuj powrównać z gmplib, ona jest dość dobrze utrzymywana. Albo rozwiń jakieś PI w szereg i sprawdź poprawność z jakimś wynikiem z netu.

0

Wykonuje się na procesorach z rodziny “x86” i “x86_64”

Dlaczego zatem niektóre części algorytmu napisałeś w czystym assembly, zamiast C/C+/C++?

Btw, nie uważasz, że funkcje długie na tysiąc linii to trochę za dużo? IMHO takiego kodu nie da się przetestować inaczej niż narzędziami w stylu QuickCheck, a to z kolei nie świadczy zbyt dobrze o bibliotece do obliczeń, w której najmniejszy błąd w dowolnym miejscu może oznaczać długie godziny stracone przez jej użytkowników :/

Btw2, nie rozumiem Twojej konwencji nazewnictwa - co to znaczy E_mem_Q_blk_I_remove i czym różni się zmienna n_0 od n_0_?

1

Nie widzę testów.
Długaśnie funkcje.
Wstawki assemblerowe, czynią dają nieprzenośny kod i na dodatek wolniejszy (kompilator potrafi cuda).
Całe repo jest mieszanką za wielu rzeczy.
Dziwna konwencja nazewnictwa - pewnie oparte o jakiś kod C, w którym nie ma przestrzeni nazw, więc tam coś takiego ma więcej sensu.

0
Patryk27 napisał(a):

Wykonuje się na procesorach z rodziny “x86” i “x86_64”

Dlaczego zatem niektóre części algorytmu napisałeś w czystym assembly, zamiast C/C+/C++?

Ponieważ C nie ma obsługi nadmiaru z mnożenia, dodawania i odejmowania, chociaż w ostatnich przypadkach pośrednio da się go sprawdzić.

Btw, nie uważasz, że funkcje długie na tysiąc linii to trochę za dużo?

Rzeczywiście, mam z tym problem. Pisałem o tym już w wątku o serwerze HTTP. Ponieważ używam wielu zmiennych lokalnych oraz obsługuję błędy procedur, nie wiem, jak wydzielać funkcjonalności.

Btw2, nie rozumiem Twojej konwencji nazewnictwa - co to znaczy E_mem_Q_blk_I_remove i czym różni się zmienna n_0 od n_0_?

E_mem_Q_blk_I_remove to jest z modułu (E) memory, obiekt (Q) blok pamieci, procedura (I) remove. Usuwa fragment przydzielonego bloku pamięci (pozostawiając go przydzielonym).
Zmienna n_0 to jest zmienna lokalna dla całej pętli, a n_0_ to zmienna tymczasowa dla następującego po niej fragmentu, wykorzystywana tylko w wybranych zagnieżdżonych blokach warunkowych zakresu jej widzialności.

0

Ponieważ C nie ma obsługi nadmiaru z mnożenia, dodawania i odejmowania

Przecież jak implementujesz wielkie liczby, to ten problem nie istnieje

0
lion137 napisał(a):

Ponieważ C nie ma obsługi nadmiaru z mnożenia, dodawania i odejmowania

Przecież jak implementujesz wielkie liczby, to ten problem nie istnieje

By szybciej przeprowadzać obliczenia, wykorzystuję dostępne instrukcje procesora do obliczeń na słowach unsigned long, z których składa się duża liczba, zamiast na pojedynczych bitach.

2

By szybciej przeprowadzać obliczenia, [...]

Z ciekawości: w jaki sposób wykonałeś benchmark porównujący wydajność Twojego ręcznie napisanego assembly vs kodu generowanego przez kompilator?

0

Jeśli to miała być reklamówka nowego języka, to jest anty-efekt. Sama estetyka kodu i identyfikatorów mnie osobiście odrzuca.

Moje zdanie w nowych nurtach w ekosystemie C / na na bazie C jest jak w dowcipie o uczuciach ambiwalentnych, nowym samochodzie i teściowej.
Nie adresuje żadnej wykazanej w analizie wady / niedostatku C.
A często jest niewiele ponad emocjonalny wyraz poczucia lepszości nad "faszystowskim" C++, i to jest ta sama pólka, co wyższość (we własnym mniemaniu) assemblorystów nad C programmersami

Nowe, tzn "nowe obiektywnie", albo "nowe dla mnie" języki są fajne, ale można ten czas spędzić bardziej pożytecznie, lepiej wybierając kierunek. Tak myślę.

0

Moduł został przetestowany przez obliczanie liczby π metodą Bailey-Borwein-Plouffe.

0

Jeśli nie dodasz testów to ludzie będą musieli wierzyć Ci na słowo i ściągając dany pakiet inwestować swój czas w coś co nawet Ty nie miałeś czasu dokładnie przetestować.
Jak myślisz ilu takich ludzi się znajdzie?

Na wypadek gdybyś szukał test case'ów do swoje biblioteki, to poniższy link może (ale nie musi) być przydatny:
https://github.com/vpiotr/decimal_for_cpp/blob/master/tests/decimalTest.ipp

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