Kalkulator ONP - C++ vs Delphi

Kalkulator ONP - C++ vs Delphi
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Z ciekawości dla sprawdzenia o ile szybciej będzie działać program napisany w C++(bo tak się mówi że Delphi jest bee), przepisałem parser z Delphi z minimalną funkcjonalnością - parsuje bez nawiasów i funkcji.

800 000 razy w pętli jest parsowane i liczone wyrażenie 2^3+123.43
Czas liczony za pomocą QueryPerformanceCounter
Wyniki: Delphi - 1.2s ; C++ - 4s.

Chciałby ktoś sprawdzić czemu taka duża różnica jest ? (może zrobiłem jakiś kardynalny błąd)
Generalnie przepisałem zamieniając case record na union ; currency na double oraz StrToFloat na atof
Projekt w Code::Blocks (no ale po dodaniu stdafxa na VS bez problemu powinno działać).
Dwie klasy - Stack i RPN, nie ma dużo kodu do oglądania :)

edytowany 2x, ostatnio: maciejmt
OO
A kod cepa jest z debugiem, bez optymalizacji itd czy normalny release testowałeś? Bo aż taka różnica jest po prostu dziwna.
msm
Jak wrzuci obydwie binarki to będzie wszystko widać na tacy :] Jak na razie czekam...
OO
Też też bo to ciekawi ciut :> Ciągle wpadają mi do łba dziwaczne przyczyny tego zjawiska :>
msm
Ja głównie liczyłem na przekazywanie każdym wywołaniu przez wartość dużych struktur ale się przeliczyłem...
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Dziwne że nie wybuchły tu jeszcze płomienie piekielne po tym jak ośmieliłeś się twierdzić że C++ jest wolniejsze od czegokolwiek poza Asemblerem.

Kod się ściąga, niestety w Delphi nigdy nie pisałem a w Pascalu na tyle dawno że nie pamiętam już na tyle dobrze żeby ocenić jakość twojego kodu.
W kodzie C++ nie widzę jakichś oczywistych błędów ale to jeszcze o niczym nie świadczy.

Mógłbyś gdzieś wrzucić binarkę z programem napisanym w Delphi wykonującym to samo zadanie?

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Nie chciałbym cię pośpieszać, ale ponawiam prośbę - wrzuć tutaj jeśli możesz binarkę z Delphi. Wynik kompilacji programu w Delphi szybszego od tego który wrzuciłeś.

Żeby się nie okazało że ten mistyczny benchmark w którym Delphi miażdży C++ trzykrotnie nie istnieje :/

MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Już leci binarka i Src, dziś byłem na wyjeździe i wróciłem godzinkę temu :)
Update 1post (raczej miał być ale się nie da)

Chyba nawet skompilowana w Debug. Konsolowa aplikacja , wynik 1.44s
Odpowiednik w C++ kompilowany w VS z O3 osiągnął chyba najlepiej 2.5s.

edytowany 4x, ostatnio: maciejmt
MF
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 13 lat
  • Postów:9
0

Matematyka na klasach nie jest dobrym rozwiązaniem. Moja rada:

Lekkie przyspieszenie C++ uzyskasz eliminując trochę wskaźników na rzecz referencji w argumentach funkcji. A przy okazji warto zmienić koncepcję stosu. Robienie dzieci na rumuńską pandę nie jest wydajne przy obliczeniach (Elem/Item). Zastosować lepiej macierz jednowymiarową i zaalokować od razu więcej pamięci, zamiast robić rozrzuty.

edytowany 1x, ostatnio: mf
MA
tak tylko chciałem pokazać różnicę wydajności tej samej koncepcji w dwóch językach. Na siłę nie mam potrzeby tu kombinować :)
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Chyba za późno żebym się tym teraz zajmował bo wychodzą mi cuda...

Najpierw sprawdziłem wynik kodu w C++ - po r.Calc(); dodałem

Kopiuj
cout << r.val << "\r\n";

Niech mi ktoś powie gdzie tu jest błąd bo oślepłem?

W wyniku na ekranie ląduje 800000 napisów 2.30214e+097 czyli prawie 10^100...
Ok, czyżby błąd? Dla odmiany sprawdziłem to co się dzieje na niższym poziomie, czyli wartość val tuż przed Clear().
Zakładając little endian dostajemy ciąg 0x40606DC28F5C28F6 który jako 64bitowa liczba zmiennoprzecinkowa zgodna ze standardem IEEE-754 (blah blah blah...) wynosi 131.43. Czyli dobrze. Sprawdzam co się dzieje w Delphi. Znalazłem ciąg 0x0000000000140DFC ... Decymalnie 6.493505e-318 czyli ponad 10^300...
Zakładam najprostszą możliwość czyli że źle ustaliłem lokalizacje w pamięci zmiennej val (IMHO mało prawdopodobne bo czym może być kopiowanie w metodzie clear do pola klasy przekazanej w parametrze z takim samym offsetem jak val w c++ zmiennej o wielkości 2 quadwordów czyli wielkości double...)
Stwierdzam że zajmę się tym później. Wracam do C::B. OK, to musi być przecież powtarzalne. Wczytujemy program wygenerowany przez C::B pod debugger. Pierwsze wykonanie kodu. I co ląduje na ekranie? 131.43...

Najlepsze jest to że to jest w 100% powtarzalne...
wth2.png

edit: Bardzo chaotycznie to wyszło, ale biorąc pod uwagę okoliczności, nic dziwnego.

Podsumowanie:

  • Dodanie couta z wyliczoną wartością powoduje że program wypisuje za każdym razem 2.30214e+097
  • Wykonanie tego samego programu pod IDĄ powoduje że program wypisuje za każdym razem 131.43
  • Delphi nic nie wypisuje bo nie mam kompilatora żeby zmienić kod, ale sprawdzanie pamięci sugeruje że wynik pod debuggerem wynosi za każdym razem 6.493505e-318
  • O_o?

PS. mam nadzieję że to tylko efekt jakiejś chwilowej mojej ślepoty, ale nie wiem na czym miałaby polegać skoro tylko uruchamiam program w różny sposób...

edytowany 4x, ostatnio: msm
Azarien
znakiem końca linii w C++ jest '\n' a nie "\r\n" - niezależnie od systemu operacyjnego.
msm
no tak... Chwilę wcześniej parsowałem trochę danych notepadem++ który przy podstawianiu (przy kodowaniu windows) wymaga \r\n,
MX
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 13 lat
0

@msm: tutaj może siedzieć błąd (RPN.cpp:24-30):

Kopiuj
            Item* it = new Item;
            it->ItemType = itArg;
            const char* ex = expr;
            while((*expr >= '0' && *expr <= '9') || (*expr == '.'))
                ++expr;
            memcpy(it->Arg, ex, expr-ex);
            queue.Push(it);

Można sprawdzić w kodzie, że to fragment wrzucający do kolejki znalezioną liczbę. Są tu aż dwa błędy:

  • Bardzo poważny: Instrukcja memcpy kopiująca liczbę do pola it->Arg. Rzecz jasna, pole nie jest wyzerowane w żaden sposób przed skopiowaniem, ani potem w żaden sposób nie dodano znaku końca łańcucha znakowego \0 - w takim razie po naszej liczbie znajdują się losowe znaki. Co, gdyby przypadkowo były to dodatkowe cyfry?
  • Trochę mniej poważny: program, już widać, nie jest "idiotoodporny". Zaakceptowałby liczbę z kilkoma kropkami, np. 1234.56.78.

Oprócz tego trzeba zauważyć, że 23+123,43 = 131,43; nie zaś 132,43 wyliczone w programie.
Tak mi się zdaje, że jest to spowodowane dziwnie odwróconą kolejnością parametrów, gdyż 32+123,43=132,43.

Edit: to może być tylko przypadek, ale dziwnym trafem 2323,43 ≈ 2,30214 * 1097 (pominąłem dodawanie, bo praktycznie nie wpływa na wynik). Dziwna zbieżność zapisu wykładnika z liczbą 123,43.


Not Found
The requested URL /wypasiona_sygnaturka.txt was not found in this brain.
-----
Human/1.0.00 (Earth) Server at Poland Port 65535
edytowany 1x, ostatnio: mnbvcX
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Faktycznie, zapomniałem o /0
Co do idioto-odporności to nie o to tu chodzi, tak na szybko przepisałem kawałek funkcjonalności w celu porównania :)
Co do niepoprawnego wyniku, to zamieściłem update (powinien być INTO, a nie push w kolejce, małe zamachnięcie się przy pisaniu :P)

edytowany 2x, ostatnio: maciejmt
msm
Planuję jeszcze zająć się tym po co prosiłem o program w delphi czyli analizą różnic między plikami .exe wygenerowanymi przez Delphi (btw. jaki kompilator bo PEiD nie dał rady?) i Gcc. W końcu z czegoś ta różnica tak czy inaczej wynika. Wtedy się okaże czy jest to kwestia faktycznie narzutu C++ czy jednak gdzieś jest subtelna różnica. Osobiście zresztą stawiałbym na to że C++ nie jest przystosowany do wielokrotnej alokacji pamięci - gdyby przepisać do C++ program w C# razem z alokacją na stercie każdej zmiennej lokalnej to działałby wolniej od brainfucka.
msm
Co nie zmienia faktu że jak dla mnie twój program nie działa poprawnie, patrz 2 posty wcześniej.
MA
zobaczę wieczorem, może z czymś jeszcze się machnąłem.
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Tak jak mnbvcX napisał - problemem był terminator cstringa, a raczej jego brak. Dzięki !
Dla Delphi zrobiłem wypisanie wyniku oraz zbuildowałem dla Release.

Tak więc MSM podaj czas w Delphi, i zbuildowany u Ciebie w CPP. U mnie ostra różnica jest :)
Potem może zobaczę czas wykonania poszczególnych elementów i się znajdzie wąskie gardło w Cpp.

edytowany 5x, ostatnio: maciejmt
0

Co się rzuca w oczy to to, że kod nie jest do końca ten sam:

C++:

Kopiuj
 if(queue.Top()->ItemType == itVal || queue.Top()->ItemType == itArg)

Delphi:

Kopiuj
if FQueue.Top^.ItemType in [itVal, itArg] then

W tym wypadku w wersji C++ masz dodatkowo wyliczenie "queue.Top()->ItemType".
Może to być zoptymalizowane / wyeliminowane automatycznie ale nie musi.
Aby było bardziej dokładnie, powinieneś odłożyć wartość do zmiennej i dopiero ją porównywać.
Ale to raczej nie jest przyczyną tak dużej różnicy.

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Chyba jednak to w większości jest alokacja - zmieniłem kod tak żeby używał domyślnych klas C++ (std::queue i std::stack) i czas wykonania spadł do 1.06. Na razie :P
Jakby nie patrzeć to używanie standardowych klas jest bardziej naturalne niż wymyślanie koła od nowa więc myślę że moje rozwiązanie jest bliższe naturalnemu w C++.

Swoją drogą fajne zagadnienie :]

Wrzucam zmieniony kod, mam nadzieję że się nie obrazisz:

Kopiuj
#include "../include/RPN.h"
#include <cstring>
#include <cmath>
#include <cstdlib>

using namespace std;

RPN::RPN()
    : stack(), queue(), val(0)
{
}

RPN::~RPN()
{
    //dtor
}

void RPN::InToPost(const char* expr)
{
    while(*expr)
    {
        Item it = Item();
        if(*expr >= '0' && *expr <= '9')
        {
            it.ItemType = itArg;
            const char* ex = expr;
            while((*expr >= '0' && *expr <= '9') || (*expr == '.'))
                ++expr;
            memcpy(it.Arg, ex, expr - ex);
            queue.push(it);
        }
        else
        {
            it.ItemType = itOp;
            it.Op = *expr;
            it.priority = Prior(*expr);

            while(!stack.empty() && it.priority <= stack.top().priority)
            { queue.push(stack.top()); stack.pop(); }

            stack.push(it);
            ++expr;
        }
    }
    while(!stack.empty())
    { queue.push(stack.top()); stack.pop(); }
}

void RPN::Calc()
{
    while(!queue.empty())
    {
        if(queue.front().ItemType == itVal || queue.front().ItemType == itArg)
        { stack.push(queue.front()); queue.pop(); }
        else
        {
            double op2, op1;
            if(stack.top().ItemType == itVal)
                op2 = stack.top().Val;
            else
                op2 = atof(stack.top().Arg);

            stack.pop();

            if(stack.top().ItemType == itVal)
                op1 = stack.top().Val;
            else
                op1 = atof(stack.top().Arg);
            stack.top().ItemType = itVal;

            switch(queue.front().Op)
            {
                case '+':
                {
                    stack.top().Val = op1 + op2;
                    break;
                }

                case '-':
                {
                    stack.top().Val = op1 - op2;
                    break;
                }

                case '*':
                {
                    stack.top().Val = op1 * op2;
                    break;
                }

                case '/':
                {
                    stack.top().Val = op1 / op2;
                    break;
                }

                case '^':
                {
                    stack.top().Val = std::pow(op1, op2);
                    break;
                }
            }

            queue.pop();
        }
    }
    val = stack.top().Val;
}

void RPN::Clear()
{
    val = 0;
    while(!stack.empty()) stack.pop();
    while(!queue.empty()) queue.pop();
}

char RPN::Prior(const char op) const
{
    if(op == '+' || op == '-')
        return 1;
    else if (op == '*' || op == '/')
        return 2;
    else
        return 3;
}

U mnie czas C++ wynosi 1.06123 s. a Delphi 0.98503 s. więc różnica niebezpiecznie dla Ciebie spada :P

luźna uwaga 1: implementacja stosu i kolejki w C++ to WTF -> pop() zwraca void przez co trzeba kombinować ze stack.top(); stack.pop(). Nie ma też czegoś takiego jak clear przez co trzeba kombinować z while(!s.empty())s.pop();

luźna uwaga 2: @Cplus -> jest znacznie większa różnica - w C++

Kopiuj
if(*expr >= '0' && *expr <= '9')

w Delphi

Kopiuj
TArgSet = ['0'..'9', '.']; if Expr[I] in TArgSet then

luźna uwaga 3: Kod Delphi był przyjemniejszy do statycznej analizy pod disassemblerem (załadowałem na krótko obydwa żeby sprawdzić wyliczaną wartość), ale może wynikało to z tego że była to wersja debug.

luźna uwaga 4: zauważ że jeszcze nic nie optymalizowałem tylko zmieniłem implementację na bardziej prawdopodobną w normalnym życiu.

edytowany 5x, ostatnio: msm
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

szybko wyedytuj, bo działasz na starej wersji (bez terminatora cstringa) oraz linijka niżej tym fragmencie ma być queue.INTO(na koniec).
No cóż, nie sądziłem, że własny stos może być tyle wolniejszy(oczywiście w Cpp) :>

edytowany 3x, ostatnio: maciejmt
0

Kasowanie w pętli stosu (Clear) to masakra, wywal to.

Użyj zamiast std::stack albo std::vector albo std::list.

OO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 13 lat
  • Postów:98
0

No, i teraz wyniki są logiczne :)


O̾..͠o
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

No zależy jak na to patrzeć.
Dla dwóch równoważnych kodów, w Delphi biło na głowę :)
Można by sprawdzić jeszcze pod VS albo Intelem, przeróbkę MSMa, o ile to przyspieszy.
Jak będzie mi się chciało, może sprawdzę użycie gotowych kontenerów Delphi.

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

@maciejmt - queue w stl nie ma metody into(), push wrzuca automatycznie na koniec.
@Cplus - nie jest tak strasznie, w końcu w ONP wszystko ostatecznie jest zużywane. Rozmiar stosu przy usuwaniu jest stały i wynosi 1, rozmiar kolejki jest stały i wynosi 0.
@O_o - zarówno Delphi jak i C++ dałoby się zoptymalizować jeszcze bardzo dużo więc konkurs uważam za nierozstrzygnięty (aczkolwiek Delphi trzeba przyznać że ma na razie przewagę - wrzucę kiedyś ten wątek jeśli ktoś będzie się upierał że C++ zawsze jest najszybszy.
@maciejmint - ale to raczej dlatego że źle podszedłeś do kwestii alokacji pamięci. W C++ alokacja pamięci to dość newralgiczna sprawa. To nie tyle kwestia wydajności języka co jego filozofii (w Javie i C# jest np. odwrotnie i alokacja to najoczywistsza rzecz pod słońcem)

edytowany 1x, ostatnio: msm
MA
no ale porównujemy C++ i Delphi, wiadomo - każdy ma coś inaczej zoorganizowane i o to w tym chodzi. Javy i C# w to nie mieszajmy : > I wyedytuj to memcpy (nie przyznaję się do tego kodu :D) To już druga taka potyczka Delphi i C++ z mej strony. Jak nasunie mi się pomysł to będę kontynuować wątek.
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Ostateczne wyniki w celu uporządkowania (Core2, 2.16):
Delphi (release) 1145ms
Delphi (kontenery biblioteczne) 1300ms

C++ (VS 2010, O3, Release, kontenery biblioteczne) - 1406ms
C++ (VS 2010, O3, Release) - 2672ms

C++ (C::B, O3, Release) - 4182ms

0

Moje wyniki:

  • delphi - release - 0.890 s
  • cpp - release - wersja udostępniona: 3.6 s
  • cpp - release - wersja po skompilowaniu VS 2010 Express: 1.63 s

Sprawdzę jak będzie ze standardowymi kontenerami...

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 8 godzin
0

wersja udostępniona dla delphi:

Turbo Delphi 2006 — 893 ms
Free Pascal 2.6.2 — 2632 ms (Release, O3)

wiedziałem że FPC generuje wolniejszy kod od Delphi, ale tutaj to poległ zupełnie.

OO
On tak zawsze miał. Pamiętam jak próbowałem do Lazarusa jakieś kontrolki dodać to on do mnie coś jak "Lazarus na razie nie obsługuje dynamicznego dodawania kontrolek więc się weźmie doda ich źródła do siebie i sam siebie przekompiluje" Trochęmu to zajeło aby na końcu wywalić AV :)
OO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 13 lat
  • Postów:98
0

Zawsze można by oszukać gdzieś i walić wstawki asma ;)


O̾..͠o
2

Zmiana wskazywanych przeze mnie wcześniej wyrażeń nic nie dała.

Po testach pod profilerem mogę stwierdzić, że głównym problemem są tu dynamiczne alokacje, które się w kółko wykonują.

W związku z tym zacząłem optymalizować wersję C++ w tym kierunku:

Delphi: 0.890 [s]

C++:
Wersja oryginalna: 1.63 [s]
Wersja ze standardowymi kontenerami (list of pointers): 1.70 [s]
Boost object pool/construct: 1.40 [s]
Boost object pool/malloc: 1.35 [s]
Boost object pool/malloc+list on pool: 1.37 [s]
Boost object pool/list on fast pool: 1.06 [s]

Można jeszcze próbować z std::vector<Item>, ale to już gruntowna przeróbka algorytmu.

Po tych zmianach znowu zajrzałem do profilera i... wyszło, że 50% czasu pożera atof().
Po zamianie na wersję stąd:
http://www.leapsecond.com/tools/fast_atof.c

wynik spadł poniżej wyniku Delphi:
Boost object pool/list on fast pool / specjalne atof: 0.603 [s] (!)

Ta najszybsza wersja jest ze źródłami w załączniku (mam nadzieje że się doda...).

To było ciekawe pytanie :-)

OO
Nieźle :) Ale dalej Delphi jest strasznie blisko, może po prostu to jakaś supah zoptymalizowana wersja.
Azarien
dochodzi kwestia tego, że naiwna wersja w Delphi była szybsza, a C++ wymagał kombinowania i zewnętrznych bibliotek żeby przegonić.
OO
Nieźle przez te pare lat dopieścili optymalizacje widocznie, ale czemu standardowe atof ciągle jest powolne skoro powstały szybsze? Chyba że to jakieś zabezpieczenia żrą herce.
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

@Cplus - nieźle :)
Na standardowych kontenerach kolejka musiała być na domyślnym deque a stack na vector<Item> - u mnie prawie 2 * szybsze!

edytowany 1x, ostatnio: msm
0

Próbowałem jeszcze z inline (patrz symbol STD_INLINE w Stack.h), ale to nic w tym wypadku nie dało.

MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Cplus ładnie tak mnie denerwować przed spaniem ? !!

Zmieniłem wersję Delphi na identyczną do C++ (Currency i Extended -> Double) oraz wywaliłem IFa przy dzieleniu (w wersji cpp go nie było) oraz przekazywanie wzoru przez const . StrToFloat zamienione na Pascalowe Val .
Osiągnałem ponad 100ms szybciej, a Twój komp jest trochę szybszy widzę więc może dogodni wersję Cpp :)

edytowany 1x, ostatnio: maciejmt
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Cplus ładnie tak mnie denerwować przed spaniem ? !!

Zmieniłem wersję Delphi na identyczną do C++ (Currency i Extended -> Double) oraz wywaliłem IFa przy dzieleniu (w wersji cpp go nie było) oraz przekazywanie wzoru przez const . StrToFloat zamienione na Pascalowe Val .
Osiągnałem ponad 100ms szybciej, a Twój komp jest trochę szybszy widzę więc może dogodni wersję Cpp :)

Rozumiem że chcesz wojny? :]

MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

No sądziłem, że Delphi wygra :)
Lubię Cpp, ale w sercu Borland ...

Żeby było sprawiedliwie, to zrobiłem dokładną wersję tego co było w Cpp (wtedy machnąłem ręką na drobiazgi) :)

Porównałem wersję CPlusa
Moja - 991ms
Cplus - 1138 (ta co była w bin - ja nie mogłem zbuildować)

Chyba Delphi jednak na tronie :>

edytowany 1x, ostatnio: maciejmt
Zobacz pozostałe 3 komentarze
hauleth
Jak tylko się dorwę w końcu do Linucha to dam rozwiązanie w Erlangu i Haskellu.
OO
O.O Ja się tu męczę z instalację boosta :< okazało się że nie wystarczy wkleić tego do projektu i trzeba zaczać myśleć :(
OO
Spróbuję przepisać do C# i Javy(tu jestem noobem więc będzie mulić bardziej niż zwykle) bo ten boost mnei już irytuje :D
msm
Przepisz do C#, ja się postaram zoptymalizować jakimiś sztuczkami za których używanie powinno się wieszać ;)
OO
Staram się pisać zoptymalizowane. Właśnie spędziłem parę godzin na lekturze różnych dziwadeł bo szukałem jak tu sprytnie przepisać rekord z case ( unia cepowa ) na C#, chciałem zrobić ze StructLayot ale jakoś w końcu nie zrobiłem tego i zostawiłem klasy z dziedziczeniem. Jak już zacznie działać to porobię by było supah cute ;)
0

@maciejmt: dodaj źródła i binarkę, bo zaczniemy płynąć jak nie będzie z czym porównać
@O_o: boosta w tym wypadku nie trzeba instalować chyba, wystarczy rozpakować do jakiegoś katalogu i dodać do ścieżki include
@Azarien: Free Pascal wspierany jest dla x maszyn, dlatego może nie być dokładnie dopasowany do x86, w każdym razie tutaj najważniejsza jest alokacja a Delphi ma ją wyśrubowaną dzięki jednemu maniakowi - Pierre le Riche (FastMM). Facet napisał manager pamięci jako niezależny programista i było to tak dobre że włączyli to do następnych wersji Delphi (z tego co się orientuję, bo dawno nie używałem).

OO
No właśnie coś tam mędziłem z tym boostem ale jakoś nie wychodzi. Bym musiał przysiąść i poczytać co to do mnie pisze bo tak na chybił trafił wklejanie nie wychodzi :(
0

Na tym kompie na którym teraz siedzę:

  • najnowsza wersja Delphi: 0.825
  • najnowsza wersja C++: 0.89

(znalazłem źródła)

OO
Jak się patrzę w kod Delphi to chyba dało by się go ulepszyć trochę, ale z braku Delphi nie sprawdzę teraz ;)
MA
  • Rejestracja:około 17 lat
  • Ostatnio:3 miesiące
  • Lokalizacja:Poznań
0

Generalnie to ONP wykorzystuje w pewnym projekcie i się kiedyś starałem aby było jak najszybsze :)
Jeśli chcecie podjąć rękawicę, to wrzucę wersję z nawiasami, unarnym minusem i plusem, seperatorem argumentów funkcji i funkcjami.
Bo tu już nie ma co za bardzo testować...

0

Tak się rozglądam po sieci i widzę, że w C++ dużo ludzi narzeka na wydajność operacji typu atof().
Można jeszcze zastosować do tego boost::spirit:

http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html

Z tego co piszą parsowanie tekstu powinno być nawet 4x szybsze od atof().

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)