欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C/C++高精度算法的簡(jiǎn)單實(shí)現(xiàn)

 更新時(shí)間:2022年12月15日 10:52:41   作者:CodeOfCC  
這篇文章主要為大家詳細(xì)介紹了C/C++中高精度算法(加減乘除)的簡(jiǎn)單實(shí)現(xiàn),方便以后需要時(shí)拷貝使用。感興趣的小伙伴可以跟隨小編一起了解一下

前言

由于上一章《C/C++ 高精度(加減乘除)算法實(shí)現(xiàn)》是基于工程項(xiàng)目考慮實(shí)現(xiàn)的,也做了一定的優(yōu)化,實(shí)現(xiàn)過(guò)程較為復(fù)雜。不利于移植和使用,且比較難以理解,時(shí)間一長(zhǎng)代碼也容易忘記,所以重新編寫了一個(gè)簡(jiǎn)化的版本,方便以后需要時(shí)拷貝使用。

一、基本原理

1、存儲(chǔ)方式

采用數(shù)字記錄高精度數(shù)字,數(shù)組的第一個(gè)元素存儲(chǔ)數(shù)據(jù)長(zhǎng)度,比如記錄數(shù)字為1024示例如下:

2、計(jì)算方式

采用模擬立豎式計(jì)算,比如加法的計(jì)算流程,如下圖所示1024+9000:

這里只給出加法的計(jì)算說(shuō)明,其他的以此類推,減法與加法基本一致。乘法和除法略有不同,通過(guò)示例圖表示也復(fù)雜,還不如通過(guò)代碼去理解,本質(zhì)的方法就是模擬筆算的立豎式計(jì)算。

二、輔助方法

1、字符串轉(zhuǎn)高精度

長(zhǎng)度記錄在數(shù)組第一個(gè)元素中

/// <summary>
/// 通過(guò)字符串初始化
/// </summary>
/// <param name="a">[in]高精度數(shù)組</param>
/// <param name="value">[in]字符串首地址</param>
static void loadStr(int* a,const char* value)
{
    //記錄長(zhǎng)度
    a[0] = strlen(value);
    for (int i = 1; i <= a[0]; i++)
        a[i] = value[a[0] - i] - '0';
}

2、整型轉(zhuǎn)高精度

/// <summary>
/// 通過(guò)無(wú)符號(hào)整型初始化
/// </summary>
/// <param name="a">[in]高精度數(shù)組</param>
/// <param name="value">[in]整型值</param>
static void loadInt(int* a, uint64_t value)
{
    for (size_t i = 1; i < 8096; i++)
    {
        a[i] = value % 10;
        value /= 10;
        if (!value)
        {   
            //記錄長(zhǎng)度
            a[0] = i;
            return;
        }
    }
}

3、比較

/// <summary>
/// 比較兩個(gè)高精度數(shù)的大小
/// </summary>
/// <param name="a">[in]第一個(gè)數(shù)</param>
/// <param name="b">[in]第二個(gè)數(shù)</param>
/// <returns>1是a>b,0是a==b,-1是a<b</returns>
static int compare(int* a, int* b)
{
    if (a[0] > b[0])return 1;
    if (a[0] < b[0])return -1;
    for (int i = a[0]; i > 0; i--)
        if (a[i] > b[i])return 1;
        else if (a[i] < b[i])return -1;
    return 0;
}

4、打印

/// <summary>
/// 打印輸出結(jié)果
/// </summary>
static void print(int* a) {
    if (!a[0])
        printf("0");
    for (int i = a[0]; i > 0; i--)
        printf("%d", a[i]);
}

三、算法實(shí)現(xiàn)

原理就不做具體介紹了,四種計(jì)算的核心都是模擬立豎式計(jì)算。

1、加法

為了保證代碼相對(duì)簡(jiǎn)單,當(dāng)b長(zhǎng)度較小時(shí)可能會(huì)做一些多余的計(jì)算,不影響結(jié)果。

/// <summary>
/// 加法(累加)
///結(jié)果會(huì)保存在a中
/// </summary>
/// <param name="a">[in]被加數(shù)</param>
/// <param name="b">[in]加數(shù)</param>
static    void acc(int* a, int* b)
{
    int len = a[0] > b[0] ? a[0] : b[0];
    memset(a + a[0] + 1, 0, (len - a[0] + 1) * sizeof(int));
    memset(b + b[0] + 1, 0, (len - b[0] + 1) * sizeof(int));
    for (int i = 1; i <= len; i++) {
        int temp = a[i] + b[i];
        a[i] = temp % 10;
        a[i + 1] += temp / 10;
    }
    if (a[len + 1])a[0]++;
}

2、減法

/// <summary>
/// 減法(累減)
///結(jié)果會(huì)保存在a中
/// </summary>
/// <param name="a">[in]被減數(shù),被減數(shù)必須大于等于減數(shù)</param>
/// <param name="b">[in]減數(shù)</param>
static    void subc(int* a, int* b) {
    memset(b + b[0] + 1, 0, (a[0] - b[0]) * sizeof(int));
    for (int i = 1; i <= a[0]; i++)
    {
        int temp = a[i] - b[i];
        a[i] = temp;
        if (temp < 0)
        {
            //借位
            a[i + 1] -= 1;
            a[i] += 10;
        }
    }
    //記錄長(zhǎng)度
    for (int i = a[0]; i > 0; i--)
        if (a[i])
        {
            a[0] = i;
            return;
        }
    a[0] = 0;
}

3、乘法

/// <summary>
/// 乘法
/// </summary>
/// <param name="a">[in]被乘數(shù)</param>
/// <param name="b">[in]乘數(shù)</param>
/// <param name="c">[out]結(jié)果,數(shù)組長(zhǎng)度必須大于等于aLen+bLen+1</param>
static    void mul(int* a, int* b, int c[]) {
    c[a[0] + b[0]] = 0;
    memset(c, 0, sizeof(int) * (a[0] + b[0] + 1));
    for (int i = 1; i <= a[0]; i++)
    {
        int j;
        int d = 0;
        //被乘數(shù)的一位去乘以乘數(shù)的每一位
        for (j = 1; j <= b[0]; j++)
        {
            int temp = a[i] * b[j] + c[j + i - 1] + d;
            c[j + i - 1] = temp % 10;
            d = temp / 10;
        }
        if (d)
        {
            c[j + i - 1] = d;
        }
    }
    //記錄長(zhǎng)度
    for (int i = a[0] + b[0]; i > 0; i--)
        if (c[i])
        {
            c[0] = i;
            return;
        }
}

4、除法

采用了升階+減法實(shí)現(xiàn)

/// <summary>
/// 除法
/// 依賴減法subc
/// </summary>
/// <param name="a">[in]被除數(shù),被除數(shù)必須大于除數(shù)</param>
/// <param name="b">[in]除數(shù)</param>
/// <param name="c">[out]商,數(shù)組長(zhǎng)度大于等于aLen-bLen+1</param>
/// <param name="mod">[out]余數(shù),數(shù)組長(zhǎng)度大于等于aLen</param>>
/// <param name="temp">[in]臨時(shí)緩沖區(qū),由外部提供以提高性能,數(shù)組長(zhǎng)度大于等于aLen-bLen+1</param>
static void divi(int* a, int* b, int* c, int* mod, int* temp) {
    //相差的階數(shù)
    int digit = a[0] - b[0] + 1;
    memcpy(mod, a, (a[0] + 1) * sizeof(int));
    memset(c, 0, sizeof(int) * (digit + 1));
    memset(temp, 0, sizeof(int) * digit);
    while (digit)
    {
        //升階        
        memcpy(temp + digit, b + 1, sizeof(int) * b[0]);
        temp[0] = b[0] + digit - 1;
        //減法
        while (compare(mod, temp) != -1)
        {
            subc(mod, temp);
            c[digit]++;
        }
        digit--;
    }
    //記錄長(zhǎng)度
    for (int i = a[0] - b[0] + 1; i > 0; i--)
        if (c[i])
        {
            c[0] = i;
            return;
        }
}

四、使用示例

1、加法

計(jì)算累加

int main() {
    int64_t n;
    int num[1024];
    int num2[1024];
    std::cin >> n;
    loadInt(num, 0);
    for (int64_t i = 1; i <= n; i++)
    {
        loadInt(num2, i);
        acc(num, num2);
    }
    print(num);
    return 0;
}

結(jié)果:

2、減法

兩個(gè)任意n位數(shù)的減法,數(shù)字1大于數(shù)字2。

int main()
{
    int a1[8096], a2[8096];
    std::string s1, s2;
    std::cin >> s1 >> s2;
    loadStr(a1, s1.c_str());
    loadStr(a2, s2.c_str());
    subc(a1, a2);
    print(a1);
    return 0;
}

結(jié)果:

#數(shù)字1
752425289999999999999652142141414141414146666676667677682324000001302461646520
#數(shù)字2
587891851201874512000000000154515100202121555555555555555555555545477910232111
#計(jì)算結(jié)果
164533438798125487999652141986899041212025111121112122126768444455824551414409

3、乘法

計(jì)算階乘

int main() {
    int64_t n;
    int num[8192];
    int num2[8192];
    int num3[8192];
    int* p1 = num;
    int* p2 = num3;
    std::cin >> n;
    loadInt(num, 1);
    for (int64_t i = 1; i <= n; i++)
    {
        loadInt(num2, i);
        mul(p1, num2, p2);
        int* temp = p1;
        p1 = p2;
        p2 = temp;
    }
    print(p1);
    return 0;
}

結(jié)果:

#階乘數(shù)
1000
#計(jì)算結(jié)果
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

4、除法

給定兩個(gè)非負(fù)整數(shù)A,B,請(qǐng)你計(jì)算 A / B的商和余數(shù)。

int main()
{
    int a1[8096], a2[8096], c[8096], mod[8096], temp[8096];
    std::string s1, s2;
    std::cin >> s1 >> s2;
    loadStr(a1, s1.c_str());
    loadStr(a2, s2.c_str());
    divi(a1, a2, c, mod, temp);
    print(c);
    std::cout << std::endl;
    print(mod);
    return 0;
}

結(jié)果:

#被除數(shù)
12458848948151231366666666666666665454545123156415641561231561213648
#除數(shù)
88484851521548496564154848456486789
#商
140802055198308817458997123299946
#余數(shù)
25178368711335236611547594127800254

總結(jié)

以上就是今天要講的內(nèi)容,本文提供的是較為簡(jiǎn)化的實(shí)現(xiàn),且每個(gè)方法基本是獨(dú)立的,可單獨(dú)拿來(lái)使用,用法也比較簡(jiǎn)單,由于采用數(shù)組第一個(gè)元素存儲(chǔ)長(zhǎng)度,接口就變得很簡(jiǎn)潔,使用起來(lái)也方便了很多。

到此這篇關(guān)于詳解C/C++高精度算法的簡(jiǎn)單實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C/C++高精度算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++類成員初始化的三種方式

    C++類成員初始化的三種方式

    如果靜態(tài)成員不滿足常量性,則不可以就地聲明,而且即使常量的靜態(tài)成員也只能是整型或者枚舉型才能就地初始化。而非靜態(tài)成員變量的初始化則必須在構(gòu)造函數(shù)中進(jìn)行。首先,先得了解一下C++支持哪幾種類成員初始化的方式,下面我們就來(lái)看看具體內(nèi)容吧
    2021-09-09
  • C/C++ 中堆和棧及靜態(tài)數(shù)據(jù)區(qū)詳解

    C/C++ 中堆和棧及靜態(tài)數(shù)據(jù)區(qū)詳解

    這篇文章主要介紹了C/C++ 中堆和棧及靜態(tài)數(shù)據(jù)區(qū)詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • QT實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘

    QT實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘

    這篇文章主要為大家詳細(xì)介紹了QT實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C語(yǔ)言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作

    C語(yǔ)言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作方法,對(duì)于了解數(shù)據(jù)結(jié)構(gòu)中鏈表的各項(xiàng)操作有很好的借鑒價(jià)值,需要的朋友可以參考下
    2014-09-09
  • C語(yǔ)言實(shí)現(xiàn)井字棋小游戲

    C語(yǔ)言實(shí)現(xiàn)井字棋小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)井字棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 關(guān)于C++出現(xiàn)Bus error問(wèn)題的排查與解決

    關(guān)于C++出現(xiàn)Bus error問(wèn)題的排查與解決

    項(xiàng)目代碼中經(jīng)常出現(xiàn)莫名其妙的Bus error問(wèn)題,并且代碼中增加很多try catch 后依然不能將錯(cuò)誤捕獲,一旦Bus erro出現(xiàn),進(jìn)程直接崩潰掉,所以本文給大家介紹了關(guān)于C++出現(xiàn)Bus error問(wèn)題的排查與解決,需要的朋友可以參考下
    2024-01-01
  • c++回調(diào)之利用函數(shù)指針示例

    c++回調(diào)之利用函數(shù)指針示例

    這篇文章主要介紹了c++利用函數(shù)指針示例,需要的朋友可以參考下
    2014-04-04
  • C語(yǔ)言與Lua之間的相互調(diào)用詳解

    C語(yǔ)言與Lua之間的相互調(diào)用詳解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言與Lua之間的相互調(diào)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • C語(yǔ)言如何利用ASCII碼表統(tǒng)計(jì)字符串每個(gè)字符出現(xiàn)的次數(shù)

    C語(yǔ)言如何利用ASCII碼表統(tǒng)計(jì)字符串每個(gè)字符出現(xiàn)的次數(shù)

    這篇文章主要介紹了C語(yǔ)言如何利用ASCII碼表統(tǒng)計(jì)字符串每個(gè)字符出現(xiàn)的次數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 一起來(lái)看看C語(yǔ)言世界中的結(jié)構(gòu)體

    一起來(lái)看看C語(yǔ)言世界中的結(jié)構(gòu)體

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言世界中的結(jié)構(gòu)體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02

最新評(píng)論