c語言-大數階乘

来源:https://www.cnblogs.com/whf10000010/archive/2022/10/13/16778713.html
-Advertisement-
Play Games

大數階乘的由來 一個正整數的階乘(Factorial)是所有小於及等於該數的正整數的積,並且0的階乘為1。自然數n的階乘寫作n!。亦即n!=1×2×3×...×(n-1)×n。階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。 但是在求解數字較大的階乘時,由於階乘累乘的性質,導致結果過大,在 ...


大數階乘的由來

    一個正整數的階乘(Factorial)是所有小於及等於該數的正整數,並且0的階乘為1。自然數n的階乘寫作n!。亦即n!=1×2×3×...×(n-1)×n。階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。 但是在求解數字較大的階乘時,由於階乘累乘的性質,導致結果過大,在C語言中,哪怕是double和Longlong都無法儲存過多的數位,而解決這個問題的辦法,最簡單的就是由數組來儲存。

大致思路

  由於是超過了一個定義變數的最大範圍,所以使用數組解決,畢竟C語言中 int的範圍為-(2的31次方-1)到(2的31次方-1),數字為-2 147 483 647~2 147 483 647。double的表示範圍為+1.111111111111111111111*2^1023(1.後面52個1)為1.7*10^308,看起來double型應該夠了的,可是,精度卻並不高,數值精度只有 15~16 位,就是說,一個 308 位長的浮點數,只有前 15~16 位的精度是可信和有保證的,超出部分就沒有精度可言了,而且,越靠後,就越不靠譜。而數組申請一個過萬的空間輕輕鬆松,每個空間再存int或double型數據,加在一起可以輸出的空間就可想而知了。

  用數組解決該問題,簡單來說就是就是將大數的各個位置用取餘取出放在數組的連續空間上,然後逆序輸出。而其中需要註意的就是化繁為簡,分解成多個子問題進行計算(是不是有些耳熟),即在已經分佈好位置的n-1的數位上進行下一次的階乘,保證了每位相乘都是一個很小的數字去乘下一個階乘數。運用雙迴圈分別進行乘數的移動和每位數字與此時乘數的計算,最後輸出。下麵是代碼:

 1 #define N 10001
 2 int a[N];
 3 double arr[N];
 4 
 5 void  factorial1(int n)
 6 {
 7     a[0] = 1;
 8     int len = 1;
 9     int tmp, next;
10     for (int i = 1; i <= n; i++)
11     {
12         next = 0;
13         for (int j = 0; j < len; j++)
14         {
15             tmp = a[j] * i+next; //當前階乘值
16             a[j] = tmp % 10; //當前位置僅保留階乘值的最後一位
17             next = tmp / 10; //保存大於10的餘下階乘值,進行下一次存儲
18             if (j >= len - 1 && next > 0) //動態增加數組長度
19             {
20                 len++;          //當數組在最後一位且存在next值時,就增加一個長度進行下一次存儲。
21             }
22         }
23     }
24     for (int i = len-1; i >=0 ; i--)//倒敘輸出數組
25     {
26         printf("%d",a[i]);
27         if (i % 5 == 0&&i!=0)//分組輸出,每組5個
28             printf(",");
29     }
30 }

  筆者前段時間剛結束對滾動數組和動態規劃的淺略總結,所以在開始便想用動態規劃解決,所以分析了一下最優化原理和無後效原則。

  • 和斐波那契數列相同,因為相乘的數是固定且沒有其它因素影響的,所以符合最優化原理
  • 前面的數列由於是固定數值,無法改變影響後面結果(比如乘到某個數時,前面的一個值要進行改變,導致該值後面一系列的數據都進行改變),所以符合無後效原則。

因此理論上來說是可以DP的,簡單來想,普通階乘可以DP嗎?當然可以(畢竟百度就能看見)。但如果這裡我們直接簡單的計算並輸出的話,數字過大時就會出現結果不准確,即:

 1 void factorial2(int n)
 2 {
 3     arr[1] = 1;
 4     arr[0] = 1;
 5     for (int i = 2; i <= n; i++)
 6     {
 7         arr[i] = arr[i - 1] * i;
 8     }
 9     printf("%lf\n", arr[n]);
10 }

  在main函數中使用

int main()
{
    int n;//階乘位數
    double a;
    scanf("%d",&n);
    factorial1(n);
    printf("\n");
    printf("double:\n");
    factorial2(n);
    return 0;
}

  輸出結果:

 

   可以看到 factorial2 函數輸出的內容是個 inf,而 factorial1 使用的數組輸出則完美的輸出了內容。而可不可以使用DP來解決大數的問題,筆者愚鈍,只是覺得行,在這裡未能解決。還請各位大佬看官如有想法,多多指教。

By the way,學個新單詞。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Vue組件 數據源 //這裡是HTML內容 這裡通過下麵的引入框架結構把數據源傳到框架中 還有匹配項 <Mytable :configList="configList" :configData="configData"></Mytable> // 引入結構組件 import myCard from ...
  • 概念 performance.now():返回值表示為從time origin之後到當前調用時經過的時間, time origin: 時間源, 時間源是一個可以被認定為當前文檔生命周期的開始節點的標準時間,計算方法如下: 如果腳本的 global object 是 Window, 則時間源的確定方式 ...
  • 在前面隨筆《基於SqlSugar的開發框架循序漸進介紹(12)-- 拆分頁面模塊內容為組件,實現分而治之的處理》中我們已經介紹過,對於相關的業務表的界面代碼,我們已經儘可能把不同的業務邏輯封裝在不同的頁面組件中,隔離變化的差異,因此界面組件化後,就可以利用代碼生成工具進行統一的界面代碼的生成了,而且... ...
  • 應用集成是解決各個系統之間信息共用中最基礎和最重要的一步。我國的商業銀行都擁有繁多、複雜的應用系統,重覆開發的情況嚴重,而且不能很好地跨系統共用數據或功能,不利於金融創新能力的提升。本文主要介紹了應用集成的發展階段,和如何運用集成技術與方式解決系統的煙囪問題,以及相比較之下的優點與局限性。還請各路專... ...
  • 對於在父類中存在的屬性,如果要在其派生類中繼續擴展屬性 可以這樣實現 1 class Valley: 2 def __init__(self): 3 self._name = None 4 5 @property 6 def name(self): 7 return self._name 8 9 @ ...
  • 數組操作 1. 數組和 for 迴圈不得不說的秘密 數組是一個連續數據存儲空間,同時帶有下標性質操作,下標範圍是 0 ~ 數組容量 - 1 ==> 利用迴圈來進行操作。 // 利用 for 迴圈給予數組中的每一個元素進行賦值操作 // 利用 for 迴圈展示數組中的每一個元素數據存儲內容 class ...
  • Kafka介紹 Kafka是最初由Linkedin公司開發,是一個分散式、支持分區的(partition)、多副本的(replica),基於zookeeper協調的分散式消息系統,它的最大的特性就是可以實時的處理大量數據以滿足各種需求場景:比如基於hadoop的批處理系統、低延遲的實時系統、Stor ...
  • JDBC和連接池01 1.JDBC概述 基本介紹 JDBC為訪問不同的資料庫提供了同一的介面,為使用者屏蔽了細節問題 Java程式員使用JDBC,可以連接任何提供了jdbc驅動程式的資料庫系統,從而完成對資料庫的各種操作 jdbc原理圖 JDBC是java提供的一套用於資料庫操作的介面API,Jav ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...