?shù)加減法看高精度計(jì)算與算法優(yōu)化實(shí)戰(zhàn))
1. 從一道題看分?jǐn)?shù)運(yùn)算的“復(fù)雜”本質(zhì)最近在輔導(dǎo)一些同學(xué)準(zhǔn)備編程競(jìng)賽和算法練習(xí)時(shí)發(fā)現(xiàn)一個(gè)挺有意思的現(xiàn)象很多人在面對(duì)“分?jǐn)?shù)加減法”這類(lèi)題目時(shí)第一反應(yīng)是“這還不簡(jiǎn)單”。但真到了像NOJ一個(gè)知名的在線判題系統(tǒng)這類(lèi)平臺(tái)上遇到標(biāo)著“復(fù)雜數(shù)據(jù)”的分?jǐn)?shù)加減題往往就會(huì)卡殼不是超時(shí)就是答案錯(cuò)誤。這背后反映出的其實(shí)是一個(gè)典型的認(rèn)知偏差——我們以為的“簡(jiǎn)單”運(yùn)算在計(jì)算機(jī)的語(yǔ)境下尤其是面對(duì)大規(guī)模、高精度或特殊格式的數(shù)據(jù)時(shí)會(huì)變得異?!皬?fù)雜”。這道“NOJ 復(fù)雜數(shù)據(jù) 分?jǐn)?shù)加減法”的題目就是一個(gè)絕佳的例子。它絕不僅僅是讓你寫(xiě)個(gè)a/b c/d然后輸出結(jié)果那么簡(jiǎn)單。所謂的“復(fù)雜數(shù)據(jù)”可能意味著輸入的分?jǐn)?shù)分子分母范圍極大比如超過(guò)long long甚至int128的表示范圍可能意味著運(yùn)算過(guò)程中會(huì)出現(xiàn)巨大的中間結(jié)果也可能意味著結(jié)果需要以最簡(jiǎn)分?jǐn)?shù)形式輸出甚至分母為1時(shí)只輸出整數(shù)。更“坑”的是題目可能不會(huì)明確告訴你數(shù)據(jù)范圍需要你自己從錯(cuò)誤反饋如Wrong Answer, Time Limit Exceeded中去反推和設(shè)計(jì)更魯棒的算法。所以今天我們就來(lái)徹底拆解一下這類(lèi)問(wèn)題。我會(huì)以一個(gè)從業(yè)多年的算法競(jìng)賽愛(ài)好者和軟件工程師的角度分享如何系統(tǒng)性地處理“復(fù)雜數(shù)據(jù)下的分?jǐn)?shù)運(yùn)算”。我們將從最核心的數(shù)學(xué)原理輾轉(zhuǎn)相除法聊起深入到高精度計(jì)算的實(shí)現(xiàn)細(xì)節(jié)再探討如何優(yōu)雅地處理輸入輸出的各種邊界情況。無(wú)論你是正在刷題的學(xué)生還是工作中偶爾需要處理精確計(jì)算的開(kāi)發(fā)者相信這套思路都能給你帶來(lái)直接的幫助。2. 核心基石最大公約數(shù)與分?jǐn)?shù)化簡(jiǎn)任何分?jǐn)?shù)運(yùn)算的起點(diǎn)和終點(diǎn)都繞不開(kāi)“化簡(jiǎn)”。一個(gè)分?jǐn)?shù)a/b在數(shù)學(xué)上等于(a/gcd(a,b)) / (b/gcd(a,b))其中g(shù)cd是最大公約數(shù)。在編程中我們通常使用歐幾里得算法輾轉(zhuǎn)相除法來(lái)高效計(jì)算gcd。2.1 為什么一定是輾轉(zhuǎn)相除法你可能知道怎么用遞歸或循環(huán)實(shí)現(xiàn)gcd但有沒(méi)有想過(guò)為什么這個(gè)方法如此高效且正確它的核心原理基于一個(gè)簡(jiǎn)單的數(shù)學(xué)事實(shí)gcd(a, b) gcd(b, a % b)。當(dāng)a % b為0時(shí)b就是最大公約數(shù)。這個(gè)算法的妙處在于它每一次迭代都將問(wèn)題的規(guī)模數(shù)字的大小顯著減小。其時(shí)間復(fù)雜度是O(log(min(a, b)))這意味著即使a和b是幾十位甚至上百位的整數(shù)也能在極少的步驟內(nèi)求出公約數(shù)。這是處理“復(fù)雜數(shù)據(jù)”時(shí)我們必須依賴(lài)的算法暴力枚舉法在數(shù)據(jù)面前不堪一擊。一個(gè)常見(jiàn)的實(shí)現(xiàn)陷阱是處理負(fù)數(shù)。公約數(shù)在數(shù)學(xué)上定義為正數(shù)。因此我們的gcd函數(shù)應(yīng)該對(duì)輸入取絕對(duì)值。// C 示例安全的gcd實(shí)現(xiàn) long long gcd(long long a, long long b) { // 先取絕對(duì)值避免負(fù)數(shù)影響計(jì)算和后續(xù)符號(hào)判斷 a llabs(a); b llabs(b); while (b ! 0) { long long t a % b; a b; b t; } return a; // 循環(huán)結(jié)束時(shí)a即為gcd }2.2 化簡(jiǎn)函數(shù)的構(gòu)建與注意事項(xiàng)有了gcd我們就可以構(gòu)建一個(gè)分?jǐn)?shù)化簡(jiǎn)函數(shù)。這個(gè)函數(shù)接收分子和分母的引用直接對(duì)其進(jìn)行化簡(jiǎn)。這里有幾個(gè)關(guān)鍵細(xì)節(jié)處理分母為零這是非法輸入必須在運(yùn)算的最前端進(jìn)行判斷。統(tǒng)一處理符號(hào)數(shù)學(xué)上我們通常約定將符號(hào)放在分子上分母保持為正。這樣在比較和輸出時(shí)會(huì)非常方便。即如果b 0則令a -a,b -b。約分計(jì)算g gcd(a, b)然后分子分母同時(shí)除以g。處理零如果分子為0我們通常將分母置為1即表示為0/1這是一個(gè)干凈的標(biāo)準(zhǔn)形式。// 化簡(jiǎn)分?jǐn)?shù)使分母為正且為最簡(jiǎn)形式 void simplify(long long a, long long b) { if (b 0) { // 根據(jù)題目要求處理通常是非法輸入這里假設(shè)題目不會(huì)給 // 在實(shí)際做題時(shí)可能直接拋出異?;蚍祷靥囟ㄖ?return; } // 1. 統(tǒng)一符號(hào)到分子 if (b 0) { a -a; b -b; } // 2. 處理分子為0的情況 if (a 0) { b 1; return; } // 3. 約分 long long g gcd(a, b); a / g; b / g; }注意這里使用了long long類(lèi)型。在NOJ的“復(fù)雜數(shù)據(jù)”場(chǎng)景下這很可能只是我們的第一道防線。當(dāng)兩個(gè)很大的數(shù)相加時(shí)即使它們本身在long long范圍內(nèi)它們通分后的中間結(jié)果分母的乘積極有可能溢出。這就是“復(fù)雜”二字的第一個(gè)體現(xiàn)也是我們接下來(lái)要解決的核心問(wèn)題。3. 應(yīng)對(duì)溢出從通分策略到高精度計(jì)算分?jǐn)?shù)加減的公式很簡(jiǎn)單a/b ± c/d (a*d ± c*b) / (b*d)。問(wèn)題就出在a*d、c*b和b*d上。假設(shè)a,b,c,d都是接近10^9的數(shù)這在int范圍內(nèi)那么b*d就可能達(dá)到10^18這剛好是long long通常為±9e18的邊界。如果數(shù)據(jù)再大一點(diǎn)或者連續(xù)進(jìn)行多次運(yùn)算溢出將成為必然。3.1 策略一優(yōu)化計(jì)算順序與提前約分在真正動(dòng)用“大殺器”高精度之前我們可以嘗試一些優(yōu)化技巧來(lái)延緩或避免溢出。核心思想在計(jì)算最終分子分母前盡可能先進(jìn)行約分。我們不是直接計(jì)算(a*d c*b)和(b*d)而是可以這樣做計(jì)算分母的最大公約數(shù)g gcd(b, d)。通分后的分母可以表示為lcm b / g * d。注意這里是先除后乘這能極大降低中間值的大小。因?yàn)閎/g和d是互質(zhì)的所以(b/g)*d就是最小公倍數(shù)且這個(gè)乘法運(yùn)算的溢出風(fēng)險(xiǎn)比直接b*d小。計(jì)算新的分子new_a a * (d / g) c * (b / g)。同樣先進(jìn)行除法d/g和b/g再與分子相乘。// 一個(gè)更安全的加法函數(shù)假設(shè)輸入a/b和c/d已經(jīng)是最簡(jiǎn)形式 void safe_add(long long a, long long b, long long c, long long d, long long num, long long den) { // 1. 計(jì)算b和d的公約數(shù) long long g gcd(b, d); // 2. 計(jì)算通分后的分母最小公倍數(shù)注意運(yùn)算順序防止溢出 // den b / g * d; // 仍有溢出風(fēng)險(xiǎn)如果b/g或d很大 // 更安全的寫(xiě)法是檢查是否溢出這里先按理想情況 den (b / g) * d; // 如果b/g * d 超出 long long 范圍這里還是會(huì)溢出 // 3. 計(jì)算通分后的分子 num a * (d / g) c * (b / g); // 4. 對(duì)結(jié)果進(jìn)行化簡(jiǎn) simplify(num, den); }這個(gè)策略在很多時(shí)候是有效的但它并不能根治問(wèn)題。當(dāng)b/g或d本身仍然很大時(shí)乘法(b/g)*d依然會(huì)溢出。此時(shí)我們就必須考慮更強(qiáng)大的工具。3.2 策略二引入高精度整數(shù)運(yùn)算當(dāng)數(shù)據(jù)范圍明確超過(guò)long long例如題目暗示或通過(guò)WA/TLE反饋得知或者我們希望寫(xiě)出一個(gè)絕對(duì)魯棒的解決方案時(shí)實(shí)現(xiàn)一個(gè)高精度整數(shù)類(lèi)BigInteger是最終手段。高精度運(yùn)算的核心是用數(shù)組或字符串來(lái)模擬手工豎式計(jì)算。對(duì)于分?jǐn)?shù)加減法我們至少需要實(shí)現(xiàn)高精度整數(shù)的以下功能構(gòu)造從字符串或long long加法、減法、乘法除法這里特指除以一個(gè)普通的int或long long類(lèi)型的數(shù)用于約分取模用于gcd計(jì)算比較大小這聽(tīng)起來(lái)很龐大但針對(duì)本題我們可以進(jìn)行簡(jiǎn)化。我們最終目標(biāo)是計(jì)算(a*d ± c*b)和(b*d)然后對(duì)其約分。約分需要gcd。因此我們最關(guān)鍵的是實(shí)現(xiàn)高精度的乘法、加法和求gcd所需的取模運(yùn)算。高精度取模運(yùn)算的簡(jiǎn)化思路我們不需要實(shí)現(xiàn)完整的高精度除法只需要實(shí)現(xiàn)“一個(gè)大數(shù)對(duì)一個(gè)小數(shù)long long范圍內(nèi)取?!?。因?yàn)樵谖覀儍?yōu)化的gcd過(guò)程中兩個(gè)數(shù)會(huì)快速減小。我們可以這樣設(shè)計(jì)用高精度類(lèi)表示分子和分母。計(jì)算gcd時(shí)如果其中一個(gè)數(shù)可以用long long表示就將其轉(zhuǎn)換然后用普通long long版本的輾轉(zhuǎn)相除法繼續(xù)。如果兩個(gè)數(shù)都很大我們需要高精度取模。但我們可以“偷懶”實(shí)現(xiàn)一個(gè)函數(shù)計(jì)算高精度數(shù) % long long。在輾轉(zhuǎn)相除法中總是用較小的數(shù)去模較大的數(shù)。我們可以在一開(kāi)始判斷如果高精度數(shù)A大于BB可能是long long或高精度則計(jì)算A % B。計(jì)算A % BB為long long可以通過(guò)模擬手工除法過(guò)程實(shí)現(xiàn)從高位到低位依次計(jì)算余數(shù)。// 高精度整數(shù)類(lèi)極簡(jiǎn)版用于說(shuō)明核心操作 class BigInteger { private: vectorint digits; // 倒序存儲(chǔ)digits[0]是個(gè)位 bool sign; // 正負(fù)號(hào) public: // ... 構(gòu)造函數(shù)、賦值運(yùn)算符等 ... // 大數(shù) % 小數(shù) (long long) long long mod(long long divisor) const { long long remainder 0; for (int i digits.size() - 1; i 0; --i) { remainder remainder * 10 digits[i]; remainder % divisor; } return remainder; } // 判斷是否在long long范圍內(nèi)并轉(zhuǎn)換 bool fitsInLongLong(long long out) const; // 與long long比較大小 int compare(long long other) const; }; // 基于此的高精度gcd BigInteger big_gcd(BigInteger a, BigInteger b) { // 盡可能將問(wèn)題降級(jí)到long long運(yùn)算 while (true) { if (a.isZero()) return b; if (b.isZero()) return a; long long la, lb; bool aFits a.fitsInLongLong(la); bool bFits b.fitsInLongLong(lb); if (aFits bFits) { // 兩者都變小了用原生long long快速計(jì)算 return BigInteger(gcd(llabs(la), llabs(lb))); } // 否則用大數(shù)取模小數(shù)的方法迭代 if (a.compare(b) 0) swap(a, b); // 保證 a b if (bFits) { // b是小數(shù)計(jì)算 a % b long long mod a.mod(lb); a BigInteger(mod); } else { // 兩者都是大數(shù)需要完整的高精度取模這里略去最復(fù)雜實(shí)現(xiàn) // 通常競(jìng)賽中數(shù)據(jù)會(huì)設(shè)計(jì)成能降級(jí)到long long或者使用現(xiàn)成的高精度庫(kù)如Java的BigIntegerPython的int a a % b; } } }在實(shí)際的競(jìng)賽編程中像C這類(lèi)沒(méi)有原生高精度的語(yǔ)言處理此類(lèi)問(wèn)題確實(shí)比較繁瑣。因此很多選手在面對(duì)明確的大數(shù)分?jǐn)?shù)運(yùn)算時(shí)會(huì)轉(zhuǎn)而使用Python或Java因?yàn)樗鼈儍?nèi)置了任意精度整數(shù)Python的int Java的BigInteger可以直接進(jìn)行運(yùn)算再配合math.gcd或BigInteger.gcd代碼會(huì)簡(jiǎn)潔安全得多。這也是一個(gè)非常重要的實(shí)戰(zhàn)技巧根據(jù)問(wèn)題特點(diǎn)選擇最合適的語(yǔ)言。4. 輸入輸出的“魔鬼細(xì)節(jié)”解決了核心計(jì)算問(wèn)題只成功了一半。OJ題目的通過(guò)與否往往還取決于對(duì)輸入輸出格式的嚴(yán)格遵循。對(duì)于分?jǐn)?shù)運(yùn)算題輸入輸出 parsing 是另一個(gè)容易失分的地方。4.1 解析多樣化的輸入格式題目可能不會(huì)友好地給你四個(gè)用空格隔開(kāi)的整數(shù)a b c d。常見(jiàn)的“復(fù)雜”輸入格式包括分?jǐn)?shù)形式輸入“a/bc/d”或“a/b - c/d”。這里可能有空格也可能沒(méi)有。多個(gè)運(yùn)算符不一定只有兩個(gè)分?jǐn)?shù)相加可能是多個(gè)分?jǐn)?shù)加減混合如“a/bc/d-e/f”。整數(shù)參與運(yùn)算某個(gè)操作數(shù)可能是整數(shù)k等價(jià)于k/1。我們需要一個(gè)健壯的解析器。思路通常是逐個(gè)字符讀取維護(hù)當(dāng)前正在解析的分子num、分母den、當(dāng)前運(yùn)算符op初始為以及一個(gè)累加器sum_num/sum_den。// 偽代碼演示解析 a/bc/d 形式 string s; cin s; long long sum_num 0, sum_den 1; // 初始累加和為 0/1 long long cur_num 0, cur_den 0; char op ; // 第一個(gè)數(shù)前面的隱含運(yùn)算符是 bool reading_denominator false; for (char ch : s) { if (isdigit(ch)) { if (!reading_denominator) { cur_num cur_num * 10 (ch - 0); } else { cur_den cur_den * 10 (ch - 0); } } else if (ch /) { reading_denominator true; } else if (ch || ch -) { // 遇到運(yùn)算符將當(dāng)前分?jǐn)?shù)cur_num/cur_den與累加器進(jìn)行運(yùn)算 // 注意當(dāng)cur_den為0時(shí)說(shuō)明剛解析完一個(gè)整數(shù)即分母為1 if (cur_den 0) cur_den 1; // 執(zhí)行運(yùn)算 sum sum op (cur_num/cur_den) calculate(sum_num, sum_den, op, cur_num, cur_den); // 重置當(dāng)前分?jǐn)?shù)設(shè)置下一個(gè)運(yùn)算符 op ch; cur_num 0; cur_den 0; reading_denominator false; } } // 循環(huán)結(jié)束后處理最后一個(gè)分?jǐn)?shù) if (cur_den 0) cur_den 1; calculate(sum_num, sum_den, op, cur_num, cur_den); // 此時(shí) sum_num/sum_den 就是最終結(jié)果記得化簡(jiǎn) simplify(sum_num, sum_den);4.2 滿足嚴(yán)格要求的輸出格式輸出通常要求是最簡(jiǎn)分?jǐn)?shù)。但還有更多細(xì)節(jié)分母為1輸出整數(shù)。例如6/3化簡(jiǎn)后是2/1必須輸出2。負(fù)號(hào)位置我們一直約定符號(hào)在分子所以如果分子為負(fù)分母為正直接輸出-分子/分母。如果化簡(jiǎn)后分子分母同為負(fù)則結(jié)果是正數(shù)。假分?jǐn)?shù)與帶分?jǐn)?shù)這一點(diǎn)至關(guān)重要很多題目要求如果結(jié)果是假分?jǐn)?shù)分子絕對(duì)值大于分母需要以帶分?jǐn)?shù)形式輸出。例如7/3應(yīng)輸出2 1/3。這意味著我們需要額外的處理。計(jì)算整數(shù)部分integer num / den注意是向零取整C中/對(duì)正負(fù)數(shù)就是這樣。計(jì)算新的分子new_num num % den。輸出如果整數(shù)部分不為0則輸出整數(shù)部分如果余數(shù)部分不為0則輸出分?jǐn)?shù)部分。兩者之間用空格隔開(kāi)。如果整數(shù)部分為0只輸出分?jǐn)?shù)部分如果分?jǐn)?shù)部分分子為0則輸出0。特別注意負(fù)數(shù)的帶分?jǐn)?shù)例如-7/3整數(shù)部分-7/3 -2余數(shù)-7 % 3 -1。但我們希望輸出-2 1/3還是-2 -1/3通常約定是輸出-2 1/3即整數(shù)部分?jǐn)y帶符號(hào)分?jǐn)?shù)部分永遠(yuǎn)為正。所以需要調(diào)整integer num / dennew_num llabs(num % den)。void output_fraction(long long num, long long den) { simplify(num, den); // 確保已經(jīng)是最簡(jiǎn)形式 if (den 0) { cout Inf endl; // 或其他錯(cuò)誤表示 return; } if (num 0) { cout 0 endl; return; } // 處理帶分?jǐn)?shù)邏輯 long long integer_part num / den; long long remainder_num llabs(num % den); // 分?jǐn)?shù)部分分子取正 if (integer_part ! 0) { cout integer_part; if (remainder_num ! 0) { cout remainder_num / den; } } else { // 整數(shù)部分為0 // 注意如果原分子是負(fù)數(shù)此時(shí)integer_part是0但num是負(fù)數(shù) // 化簡(jiǎn)后符號(hào)在分子所以直接輸出 num/den 即可 cout num / den; } cout endl; }在動(dòng)手寫(xiě)代碼前務(wù)必仔細(xì)閱讀題目的輸入輸出說(shuō)明并用題目給的樣例進(jìn)行充分測(cè)試。往往一個(gè)空格、一個(gè)換行符的差異就會(huì)導(dǎo)致“格式錯(cuò)誤”。5. 實(shí)戰(zhàn)整合與測(cè)試策略現(xiàn)在我們把所有模塊組合起來(lái)形成一個(gè)完整的解題框架。這個(gè)框架需要靈活應(yīng)對(duì)不同級(jí)別的“復(fù)雜度”。5.1 分層級(jí)的解決方案我建議按以下順序嘗試和思考Level 1: 基礎(chǔ)版假設(shè)數(shù)據(jù)在long long范圍內(nèi)使用優(yōu)化后的通分和化簡(jiǎn)方法。實(shí)現(xiàn)正確的輸入解析和輸出格式化。這能解決大部分普通分?jǐn)?shù)題。Level 2: 防御版在Level 1的基礎(chǔ)上在乘法運(yùn)算前加入溢出檢查。例如判斷a/b和c/d在計(jì)算a*d時(shí)是否會(huì)溢出。如果會(huì)則自動(dòng)切換到更高精度的計(jì)算如果自己實(shí)現(xiàn)了高精度類(lèi)。或者直接使用__int128如果編譯器支持來(lái)作為中間計(jì)算的類(lèi)型這是一個(gè)非常實(shí)用的技巧它能處理到約10^36的數(shù)覆蓋絕大多數(shù)競(jìng)賽題。// 使用 __int128 擴(kuò)展范圍 __int128 ia a, ib b, ic c, id d; __int128 new_num ia * id ic * ib; __int128 new_den ib * id; // ... 然后再化簡(jiǎn)注意__int128需要自己實(shí)現(xiàn)gcd和輸出Level 3: 通用版使用Python或Java。這是應(yīng)對(duì)“復(fù)雜數(shù)據(jù)”最省心的方法。Python代碼示例from math import gcd import sys def parse_and_calculate(s): # 假設(shè)s是 a/bc/d 形式 # 這里簡(jiǎn)化處理用eval是危險(xiǎn)的僅作思路演示 # 更安全的是用正則或手動(dòng)解析 parts s.replace( , ).split() # 簡(jiǎn)單拆分 total_num, total_den 0, 1 for part in parts: if / in part: num, den map(int, part.split(/)) else: num, den int(part), 1 # 通分相加 total_num/total_den num/den lcm total_den // gcd(total_den, den) * den total_num total_num * (lcm // total_den) num * (lcm // den) total_den lcm # 每一步都化簡(jiǎn)防止中間結(jié)果過(guò)大 g gcd(total_num, total_den) total_num // g total_den // g return total_num, total_den # 輸出部分同理處理帶分?jǐn)?shù)5.2 系統(tǒng)化的測(cè)試用例設(shè)計(jì)自己構(gòu)造測(cè)試數(shù)據(jù)是調(diào)試的關(guān)鍵。不要只依賴(lài)OJ的樣例。你應(yīng)該構(gòu)造一個(gè)測(cè)試集覆蓋以下情況常規(guī)運(yùn)算1/2 1/3,-1/4 1/2。邊界值分子分母為0如果題目允許分子分母為1非常大的質(zhì)數(shù)相加減。溢出檢查構(gòu)造(2^62)/1 (2^62)/1看你的long long方案是否會(huì)溢出?;?jiǎn)觸發(fā)2/4 2/4結(jié)果應(yīng)為1/1輸出1。帶分?jǐn)?shù)輸出7/3,-7/3,3/2,-1/2。復(fù)雜表達(dá)式1/2-1/31/6結(jié)果應(yīng)為1/3。長(zhǎng)表達(dá)式壓力測(cè)試連續(xù)加100個(gè)1/100看是否溢出或超時(shí)。將你的程序在這些數(shù)據(jù)上運(yùn)行與一個(gè)可信的參考如Python直接計(jì)算進(jìn)行對(duì)比。我個(gè)人的習(xí)慣是寫(xiě)一個(gè)簡(jiǎn)單的Python腳本隨機(jī)生成大量測(cè)試數(shù)據(jù)用我的C程序計(jì)算再用Python的fractions.Fraction驗(yàn)證結(jié)果快速定位問(wèn)題。5.3 一個(gè)常見(jiàn)的“坑”計(jì)算過(guò)程中的中間狀態(tài)化簡(jiǎn)這是很多初學(xué)者甚至有些經(jīng)驗(yàn)的選手都會(huì)忽略的一點(diǎn)。我們之前提到在累加多個(gè)分?jǐn)?shù)時(shí)每加完一次就應(yīng)該立即化簡(jiǎn)。而不是等到所有分?jǐn)?shù)都加完后再化簡(jiǎn)。為什么考慮計(jì)算1/2 1/3 1/6。錯(cuò)誤做法先算1/21/3 5/6再算5/61/66/61??雌饋?lái)沒(méi)問(wèn)題但如果分母更大呢1/1000000000 ... (加一千萬(wàn)次)中間的分母會(huì)急劇膨脹到不可想象的大小導(dǎo)致即使最終結(jié)果很小中間計(jì)算也早已溢出。正確做法1/21/3得到5/6立即化簡(jiǎn)這里已是最簡(jiǎn)。然后5/61/66/6化簡(jiǎn)為1/1。在多次累加中及時(shí)化簡(jiǎn)能始終保持分子分母在相對(duì)較小的范圍內(nèi)。這個(gè)原則在實(shí)現(xiàn)解析多個(gè)分?jǐn)?shù)加減的循環(huán)時(shí)必須牢記。