鱼C论坛

 找回密码
 立即注册
查看: 2382|回复: 0

[技术交流] 任何数的n次方高精度计算

[复制链接]
发表于 2014-10-23 18:13:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
最近闲着无聊,写了下面160行左右的代码

数据类型为unsigned int ,只会计算正整数
代码看起来可能有点长

整个思路是,以四位为一个单位,超过四位就新建节点
以此推进,把一个很大的数拆散为一个个单元计算

输出方面也要注意补零,比如“10024”按四位截断后成为“0024”,int型数据重新输出会变成“24”

此段代码计算2的100w次方所用时间为:930s
如果有朋友有空,欢迎对此代码提出优化建议,或者找出bug
更希望下面评论不是一片“谢谢无私分享”之类的回复,而是对此段代码的批评或者建议

以下为代码:


#include<stdio.h>
#include<time.h>
#include<stdlib.h>

long start = 0;
float timespend = 0;

typedef struct List
{
        unsigned int Data;
        unsigned int Logo;
        struct List *Prior;
        struct List *Next;
}LIST;

typedef struct BaseNum
{
        unsigned int Radix;
        unsigned int Power;
}BASENUM;

void Cmd(BASENUM *Get);
LIST *CreateList(void);
LIST *AddList(LIST *Flag);
LIST *Calculation(BASENUM *Get, LIST *Head);
void HighPrecitionPrintf(LIST *Head);
int main(void)
{
        BASENUM Number;
        LIST *Head;

        Cmd(&Number);
        Head = CreateList();
        Head = Calculation(&Number,Head);
        HighPrecitionPrintf(Head);

        return 0;
}

void Cmd(BASENUM *Get)
{
        printf("Confirm Radix:");
        scanf("%d",&Get->Radix);

        printf("Confirm Power:");
        scanf("%d",&Get->Power);
}

LIST *CreateList(void)
{
        LIST *Head;

        if (NULL == (Head = malloc(sizeof(LIST))))
        {
                printf("Creating Failure!\n");
                return NULL;
        }
        Head->Logo = 1;
        Head->Next = NULL;
        Head->Prior = NULL;

        return Head;
}

LIST *AddList(LIST *Flag)
{
        if (NULL == (Flag->Next = malloc(sizeof(LIST))))
        {
                printf("Creating Failure!\n");
                return NULL;
        }
        Flag->Next->Prior = Flag;
        Flag->Next->Logo = (Flag->Logo) + 1;
        Flag->Next->Next = NULL;
        return Flag;
}

LIST *Calculation(BASENUM *Get,LIST *Head)
{
        start = clock();                   //开始计时

        Head->Data = Get->Radix;
        LIST *Temp = Head, *Flag = Head;
        int High = 0;

        if (0 == Get->Power)    //若次方为0则直接输出1并返回
        {
                Head->Data = 1;
                return Head;
        }

        if (0 == Get->Radix)    //若根为0则直接输出0并返回
        {
                Head->Data = 0;
                return Head;
        }

        (Get->Power)--;             //求一个数的n次方只需要循环n-1次
        while ((Get->Power)--)
        {
                Temp->Data *= Get->Radix;
                while (NULL != Temp->Next || Temp->Data / 10000)
                {
                        /*
                        *只要当前节点不是最高位或当前节点数据超出四位数均能进入此模块
                        *若当前节点为预备最高位且节点数据不超过四位,则默认为最高位并跳出此模块
                        */
                        High = Temp->Data / 10000;
                        Temp->Data %= 10000;
                        if (0 != High && NULL == Temp->Next)   //若有进位 则新建节点存放并跳入下一次循环
                        {
                                AddList(Temp);
                                Temp = Temp->Next;
                                Temp->Data = High;
                                continue;
                        }
                        Temp = Temp->Next;

                        Temp->Data *= Get->Radix;
                        Temp->Data += High;
                }
                if (0 == Get->Power)Flag = Temp;     //获取最高位的节点
                Temp = Head;
        }
        return Flag;               //Flag指向最终数的最高位
}

void HighPrecitionPrintf(LIST *Head)
{
        LIST *Temp = Head;
        int Count = 0,DataCopy = 0,Flag = 0;

        printf("%d",Temp->Data);
        Head = Temp->Prior;
        free(Temp);
        Temp = Head;

        while (NULL != Temp)
        {
                DataCopy = Temp->Data;

                //下列if-else if组合用于补零  清除类似“10024”进行四位截断存储后再输出成为“24”的情况
                if (!(DataCopy % 10) && !(DataCopy / 10))
                {
                        Count = 4;     //只有当四位数均为零才会触发
                        Flag = 1;      //当四位数均为零,设置标记,防止额外补零
                }
                else if (!(DataCopy / 10))Count = 3;
                else if (!(DataCopy / 100))Count = 2;
                else if (!(DataCopy / 1000))Count = 1;

                while (0 != Count)             //若条件直接写Count--  则Count = 0时进入循环会进行65535次补零
                {
                        printf("%d", 0);           //进行补零
                        Count--;
                }
                if (!Flag)printf("%d", Temp->Data);          //至此本节点完整输出

                Head = Temp->Prior;
                free(Temp);
                Temp = Head;
                Flag = 0;                      //撤销标记
        }
        printf("\nPrintf Completed!\n");
        printf("time:%0.3f s\n", timespend = (clock() - start) / 1000.0);
}

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-12 08:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表