Вопрос по алгоритму
От: smsteel  
Дата: 07.09.09 19:57
Оценка: :)
Имеется сумма 1/1+1/2+...+1/n. Учитывая особенности с++, результат суммы 1/n + 1/(n-1)+...+1/1 даст более точный результат.
Вопрос 1: что за особенности? Интерпритатор как-то преобразует эти суммы?
Вопрос 2 (более важный): как получить еще более точный результат суммы такого ряда?


08.09.09 13:30: Перенесено модератором из 'C/C++' — Кодт
Re: Вопрос по алгоритму
От: Erop Россия  
Дата: 07.09.09 20:20
Оценка:
Здравствуйте, smsteel, Вы писали:

S>Вопрос 1: что за особенности? Интерпритатор как-то преобразует эти суммы?

Ну маленькие числа лучше с маленькими складывать, а большие с большими...
Только у С++ обычно не интерпретатор...

S>Вопрос 2 (более важный): как получить еще более точный результат суммы такого ряда?

Ну аналитически попробовать что-нибудь изобразить, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Вопрос по алгоритму
От: korzhik Россия  
Дата: 07.09.09 20:21
Оценка: +1
Здравствуйте, smsteel, Вы писали:

S>Имеется сумма 1/1+1/2+...+1/n. Учитывая особенности с++, результат суммы 1/n + 1/(n-1)+...+1/1 даст более точный результат.

S>Вопрос 1: что за особенности? Интерпритатор как-то преобразует эти суммы?
S>Вопрос 2 (более важный): как получить еще более точный результат суммы такого ряда?

1/1+1/2+...+1/n — это гармоническое число (Harmonic number). Информацию о том как его высчитывать можно найти в интернете.
Re: Вопрос по алгоритму
От: Pzz Россия https://github.com/alexpevzner
Дата: 07.09.09 22:10
Оценка:
Здравствуйте, smsteel, Вы писали:

S>Имеется сумма 1/1+1/2+...+1/n. Учитывая особенности с++, результат суммы 1/n + 1/(n-1)+...+1/1 даст более точный результат.

S>Вопрос 1: что за особенности? Интерпритатор как-то преобразует эти суммы?

Нет, процессор округляет результат арифметических операций из-за конечной разрядности плавающих чисел. Когда вы прибавляете маленькое число к большому, теряется больше информации (из маленького числа), чем когда вы прибавляете маленькое число к маленькому.

S>Вопрос 2 (более важный): как получить еще более точный результат суммы такого ряда?


Аналитически
Re: Вопрос по алгоритму
От: smsteel  
Дата: 07.09.09 22:49
Оценка:
Вопрос решен, всем спасибо.
Re[2]: Вопрос по алгоритму
От: Аноним  
Дата: 09.09.09 00:10
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, smsteel, Вы писали:


S>>Имеется сумма 1/1+1/2+...+1/n. Учитывая особенности с++, результат суммы 1/n + 1/(n-1)+...+1/1 даст более точный результат.


Забавно, но это не так.

Пусть n=184913
Тогда, при складывании по возрастанию ошибка будет 5.02E-0016,
а при складывании по убыванию она будет в 30 раз больше: 1.55E-0014

http://forum.ixbt.com/topic.cgi?id=40:3019-4
Re: Вопрос по алгоритму
От: vadimcher  
Дата: 09.09.09 02:04
Оценка:
Здравствуйте, smsteel, Вы писали:

S>Имеется сумма 1/1+1/2+...+1/n. Учитывая особенности с++, результат суммы 1/n + 1/(n-1)+...+1/1 даст более точный результат.

S>Вопрос 1: что за особенности? Интерпритатор как-то преобразует эти суммы?
S>Вопрос 2 (более важный): как получить еще более точный результат суммы такого ряда?

Мне кажется что здесь ситуация такая. Допустим, у тебя числа хранятся в таком виде (собственном формате, но близком к тому, как это на самом деле хранится): всего, например, ты под число отводишь 4 десятичных разряда, из них 3 разряда -- под число, а один -- под порядок, и число [abc,d] -- это в твоей системе (abc)*10^d. Теперь, допустим, ты хочешь прибавить 1+0.005+0.005. В твоей системе это запишется как [001,0]+[005,-3]+[005,-3], но сумма первых двух даст 1.005, что в силу ограниченности представления даст просто [001,0], прибавление третьего слагаемого результат также не изменит. Наоборот, если сначала сложить два последних слашаемых, то они дадут 0.01 или [001,-2], что в сумме с первым даст [101,0] -- правильный результат.

Короче, при сложении мелких слагаемых может "накопиться" сумма, которая уже добавит что-то в младшие разряды больших чисел, в то время как сложение, начиная со старших слагаемых, сразу делает сумму большой и не дает маленьким слагаемым "реализоваться".

Еще особенность в данном примере в том, что 1/k -- это периодическая дробь, причем период достаточно большой для почти всех (ну или многих) больших k. Тогда, если складывать маленькие сначала, то их период не "съесться" бОльшими числами. Короче, при больших k больше цифр значимых после запятой, и при сложении между собой они в большей степени учитываются.

Самому интересно стало, когда это себя проявит... Вот я набросал пару строк: класс Fraction (который вычисляет сумму ТОЧНО, как дробь, а затем выводит ее в десятичном виде обычным делением столбиком):
template<typename _int_>
struct Fraction {
    _int_ n;
    _int_ d;
    Fraction(_int_ n_, _int_ d_): n(n_), d(d_) {}
    Fraction & operator += (Fraction & frac) { n = n * frac.d + d * frac.n; d *= frac.d; Cancel(); return *this; }
    void Cancel(void) { _int_ r1 = n, r2 = d; if (r2 != (_int_)0) while ((r1 %= r2) != (_int_)0 && (r2 %= r1) != (_int_)0) {} n /= (r1 += r2); d /= r1; }
    void OutDouble(int precision = 100) const { _int_ r = n; for (int i = 0; i < precision; ++i) { cout << (_int_)(r / d); if (!i) cout << '.'; r = (_int_)(r % d) * (_int_)10; } }
};

Для класса Fraction в качестве "рабочего" типа я использую класс ttmath::Int<256> -- это 1024-байтное целое.

Три различных способа суммирования ряда: с головы, с хвоста, попеременно (1/1+1/n+1/2+1/(n-1)+...). По идее, результат второго способа должен быть самым лучшим. Далее примеры расчета первых N слагаемых для которых посчитано четыре значения: точное значение, а далее три способа расчета:
1000:
7.485470860550344912656518204333900176521679169708803665773626749957699349165202440959934437411845081
7.48547086055034330000000000000000000000000000000000000000000000000000000000000000
7.48547086055034060000000000000000000000000000000000000000000000000000000000000000
7.48547086055034420000000000000000000000000000000000000000000000000000000000000000

2000:
8.178368103610282409577656571641693687935466740912487740220409263201420558139784388794627554873311364
8.17836810361028380000000000000000000000000000000000000000000000000000000000000000
8.17836810361027840000000000000000000000000000000000000000000000000000000000000000
8.17836810361030510000000000000000000000000000000000000000000000000000000000000000

3000:
8.583749889959187114343792091258973719948621235283024344568679854123127295864172259207385883442945304
8.58374988995916870000000000000000000000000000000000000000000000000000000000000000
8.58374988995918460000000000000000000000000000000000000000000000000000000000000000
8.58374988995921480000000000000000000000000000000000000000000000000000000000000000

При 3000 уже видно некоторое отставание...
4000:
8.871390299795227230713699728239907800023031429075073965792337032251330893271965061733732535202005884
8.87139029979519830000000000000000000000000000000000000000000000000000000000000000
8.87139029979522320000000000000000000000000000000000000000000000000000000000000000
8.87139029979520370000000000000000000000000000000000000000000000000000000000000000

Здесь уже отставание более заметное...
5000:
9.094508852984436967261245533393439391782987811303811450616283852090532830500877899391409299236919740
9.09450885298440430000000000000000000000000000000000000000000000000000000000000000
9.09450885298442910000000000000000000000000000000000000000000000000000000000000000
9.094508852984390000000000000000000000000000000000000000000000000000000000000000

И здесь... Но в любом случае порядок погрешности на много порядков меньше порядка слагаемых.

Кстати, точное значение суммы первых 5000 слагаемых, если верить тому классу, что выше, в виде неприводимой дроби:
659623649559621432126336933383193729260848318892404027333517115521100525541316523072979107322459171613691837183951487661
966476809122548346163385286694690349878705131491862640137164411673210272080148676949797860479113407454434744754705431897
253015328515294290415809653442681365310988313565177318131016159166788573974508759137026640130789344741103257231054780021
170708211553851910329718802808846485397454574731997516579024601045733467195781356192205947355552917047789319804461705772
633068013748924167331191725591062331529020365084683255668594858608409202558729804363740731361196006611576240811406973799
460944486403408553796346712447429569906266248719567465105302819123430989544392681106873354018521994893973818318320095911
564139040863319710411194581794985143253299776516173980509789487989538939156242769895635896847674794200281847578210412682
164900069032245882325319331826708552824979341858775409083588995202741428160995150983675490081833220549284646690543753970
026229676977188244062665215493845997418692450894987513446066152541405696250034946387454429478572302111678251574110501710
700892812164786666698585592777606586761122723426551283443672603697905407962532066793601582381457220347615454148454090413
652171656656742068308887201368356407939791462550908886827013698357994801541566586885867154861189963892496989526513529714
999753615065639180146460119038919106802922808458700589653921774494347404395285934602527461773853368717108958788926137852
347704993748587540957034132791855246758856735670871545671967188152127830707348707579802212571407551815388318364267629688
073637466104477643387137009916638023114188447988227890360787610975329553967916457963649473071483787497727210973514519771
255631231535376287126191305830248453486510739290667093773332302740982277510049601997692653419765334112613347764181048602
842801434931412888896694529629156905540521007028831572804210439039513913461918529515138545075921446847887540110743326185
358735389687122056743743922097402266016356564144339856993437711723668020672891718804666635671191843029355136541022054310
206747527922722831535207375283612887084453794186230299020450521033317479278517938122099594511676039122524549890282468265
302769
/
725298815167089064404827905841530875606619635021389804668211720181686319876273191251920794602162131539135089242884338631
291987551564832532864362250545443086430257722904403492162535614737868964198128487745902930882705088764383710514401777793
463530392707215557642745411509957314840819707899395499787458448814058493693210980159502447813838784918509391179685897062
068391670643037713740970385360210639107187923657082038477991025770136457744773615911429795513734290914758075619722906837
115646120765583075223618025412932928650048044927029674983742310329507921474279932310867082260871441978471290532062079911
588852279122055867399568264567258053339701353167659540015339507373073201194224762599136991501024482003380035351336154300
845874268964166202474472626459069931676589538163895659360086401567254668154708973635019501314249818890102922522879745606
486226184139514010352969579666754770220228537247856247914008710970517823536726683618666497619249692326266311477089643987
739416633713344787641004826483001468766369144116306479274393849339278756042790850613904162315985678706660492836635373806
921920449911922539970839670712245615551583845322644369572662445408912006546132279306247798136636441560742949086021015748
814531776399208018453239575648654288196972655882507348440831106198732809581692249798187975043528302641082353135317206874
911351866968865371974330085561876933965169798710944800902688906582624233205447915705935353739327917537265191803625195778
076522340066585367869611473541804155969459784311525284176183196596522660421263244363847435453709897656462026840372537229
132245632918589004431408501966190734002827863517044281170464468102120362732479301219763048037893577683215535115402573683
197323387228244823860646708713812305557705474680344976739524410300423579731935435487227102952763862391508391266950227683
538349264553335167300253495660001253890786419134619241656478703797023760590653964281362860348972005686932972228946363556
125492792817198770029083614696320157735891562369940756155639236485293691993828262329348805369278499911213254455154484442
953748338565580241380084947985594145482015660766600224064225069858434924631262386154984426081604155541328085049223490432
00000

А вот зайца кому, зайца-выбегайца?!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.