-
-
[原创]Super Calculator using by Language C++
-
发表于: 2009-10-8 14:24 6110
-
1. 这个 Calculator 是我在 2003年至2004 年研究怎么破解 RSA Cryptosystem 时 ( 【分享】植基于RSA加密算法频率特性之研究, 【原创】植基于RSA加密算法频率特性之研究--- Utilities,特别设计的一个软件。
2. 设计者是我的朋友张先生,并非我本人,他只是应我要求,给我一个符合我要的软件。
3. 这个 Calculator 很强大,但不是很完美,有意继续 modify 它的人,希望你们成功。
/* README - CALCL 32\64-Bit 核心源码 Version 1.0.5.4 */
-------------------------------------------------------------------------------
※ calcl 核心源码并不纯粹为自由软件,在使用这些源码相关档案之前,请先同意并遵守
作者的以下条件:
0. 基础条件:本源码仅授权于愿意提供助益给所有人类的程序设计者使用。
1. 必须遵守非商业使用的条件(不能涉及帮自己或他人赚钱之行为),必须纯为义务
公益性质。
2. 修改源码后之程序(含执行文件与修改之源码),都必须提供所有人可免费和直接取
得(含取得管道),但我亦准许发行者得收取适当的硬件工本费 (只可涵盖必须的
硬件成本,如 CD、软盘、邮寄费用等),并绝对遵守上述 0. 和 1. 之条件。
3. 不可将本源码改写或应用于破坏或不利他人的软件上。
4. 对于学生或任何研究者不可将本源码用于其作业或论文或研究等等之某一部分;
唯其作业或论文或研究等等的明显处,有清楚书名本源码的出处与作者(含合法
改码者),且确定避免不当得利者可除外(不当利益含成绩、金钱、任何名利作用
等)。
5. 若违反上述任一条件则视为侵权,作者(含支持上述条件的其它合法改码者)将有
权利控告你的侵权行为,并可因之要求提出赔偿。
6. 知识与技术的取得在理想上应属于自由的层面,必须开放给全人类一起分享,我
提供 Calcl 核心是立于此基础之上的,所有使用 Calcl 核心的程序设计人都应
该知道并遵守这一点;但本人仍同意对于非运算技术相关部分的程序代码,比如介
面环境设计或其它不重要的部分,所有使用到 Calcl 核心的设计者可以保留权
利去决定对该部分源码公开与否,而判别这部分可私藏的源码必须遵守与根据于
以下的规则:
<1> 该源码是设计者的个人特色而无关 Calcl 运算技术。
<2> 缺少该部分源码并不会造成问题,或该源码是具有因人而异的可替代性质而
属于大众皆可制作的独立部分。
由上知道只要你是修改了 Calcl 核心码都必须遵守上述各项规定来公开你的新
版 Calcl 核心码,而假如制作像是主函式 main() 来跑 Calcl 核心应用的源码
这部分,你则可以在不涉及更动 Calcl 核心码的情况下决定该部分源码要公开
或否。
但无论你的私藏源码公开与否,所有 Calcl 核心编程者都至少必须针对一般大
众公开、免费的提供你的程序的可执行文件于网络上或其它可轻易取得的管道,以
造福人群。
- 如果你不愿同意上述者,请马上删除 Calcl 核心码档案不要使用它,以免触法。
- 如果你同意并遵守这些条件限制,即刻起你成为本源码的合法使用者,欢迎改码助益社
会大众,谢谢!
- Copyright (C) 2003-2004 张岑宇 cty personal
-------------------------------------------------------------------------------
使用简体中文者请注意:
由于作者本人从小就是繁体中文的背景,故我的核心源码里的中文字亦属之;对使用简体
中文的人士而言,在编译 Calcl 核心源码之前请先使用翻译软件将各源码档案的繁体中
文字转成简体中文字,以利进行你的程序开发。
-------------------------------------------------------------------------------
我目前使用的 IDE 开发环境编译器是 Dev-C++ 4.9.8.1,这些源码在这个编译器上可成
功编译,并可在 Fedora Core 1 / Mandrake 9.2 的 KDE 的 KDevelop 编译成功。
本核心码数据夹不含主函式﹝如 main()﹞的档案,只有包含 calcl 运算核心档案,程序
员必须自行撰写主函式来应用 Calcl 核心码到你的程序里,在使用 calcl 核心之前得引
入档案 calclCombine.h 与 calclCombine.cpp,且必须宣告 StrCalclKNL 类别的对象并
使用之才可生效。
-------------------------------------------------------------------------------
- 参考码﹝非绝对﹞:
先用整合型编译器(如 Dev-C++)设立项目 Project,并放置档案在一个专用的数据夹内,
接着请将取得的核心源码 CalclConstruct 资料夹也复制到该数据夹内。
﹝为增加编译完成后的程序运算速度,请选择各编译器的最佳化(speed)﹞
﹝用 Dev-C++ 的提升速度:项目→项目选项→编译器讯息→细部最佳化和高度最佳化﹞
开始做程序代码,请开新档案(含有主函式的 cpp 档案),假设取名为 main.cpp 的主函式
档案,参考内容若下:
/*
** main() -- 示范在 Windows 操作系统的 Console 使用 calcl 核心码
**
** Copyright (C) 2003-2004 张岑宇 cty personal
**
** Chang, Tsern-Yeu <ciqzi2r5@ms77.hinet.net>
*/
#define __DEBUG 0 //1:包含核心部分除错叙述(in terminal),0:正式版
#define _SYS32 //定义 32-Bit 系统,另一选择(预设) 64-Bit: _SYS64
/* 以下三行定义(#define)是必须的所以不可漏掉 */
#define OPERATIONSYS 2 //定义操作系统 2:Windows,1:Linux
#define GUI 0 //定义图形接口 0:无
#define PROGRAMNAME "calcl" //定义你的程序名称,关系交换用暂存目录名称(重要)
/*
** 在这里(Windows 环境)引入 calcl 核心码(含定义与实作)
**
** 定义文件里包含许多公用标头文件,不必再额外引入下列档案:
**
** <iomanip> <iostream> <cstdio> <cstdlib> <cmath> <ctime>
** <sys/types.h> <sys/stat.h> ...
**
** Linux :<fcntl.h> <unistd.h> ...
** Windows:<windows.h> <io.h> <direct.h> <conio.h> ...
**
** 注:<1>在 Linux 的路径里请使用 '/' 来取代下面的 '\'
** <2>视情况在必要时给予完整的 calcl 核心码所在路径
*/
#include "Calcl64ConstructDynamic\calclCombine.h" //引入定义
#include "Calcl64ConstructDynamic\calclCombine.cpp" //引入实作
/*
** 函式开始前必须了解:
**
** n, m, LP_preci 是全域变量宣告在 Lcalc_base.cpp 里
**
** n :决定运算值总位数,亦配置储存数值的内存的大小
** m :小数字所在元素(小数点右边第一位所在),区隔数值的整数与小数
** LP_preci:最小精度位所在元素,是计算到最小的小数字数所在
**
** n, m, LP_preci 完全控制 StrCalclKNL 类别的对象,所以很重要
**
** 编译连结产生执行档后,在执行期可用核心 set 指令设定 n, m, LP_preci
**
** 总位数在 32-Bit = 4 * n 位
** 总位数在 64-Bit = 8 * n 位
**
** 若欲设定精度者必须注意范围:n - 2 > m > LP_preci > 0
*/
int main()
{
/*
** 这里宣告 StrCalclKNL 类别的对象
** 这对象会产生:交换用暂存目录、环境设定文件、执行期间的运算用交换档案等
*/
StrCalclKNL SCK; //宣告 StrCalclKNL 类别的对象 SCK
double duration; //记录核心(进入到离开)的运算时间(秒)
system("CLS"); //清除 Console 屏幕,Linux 用 system("clear");
while(true)
{
//指示输入,亦可使用 printf("Input: ");
cout << "Input: ";
//读入表达式的字符串,亦可使用 scanf("%s", SCK.Str);
//注意 cin 或 scanf() 不能读入空格,但换 gets() 则可以
cin >> SCK.Str;
//若读入 q ,则结束循环
if(SCK.Str[0] == 'q' && SCK.Str[1] == '\0') break;
//进入运算里
SCK.calclKNL(duration);
//印出答案,亦可使用 printf("Anser: %s\r\n", SCK.Str);
cout << "Anser: "<< SCK.Str << endl;
//印出花费时间,亦可使用 printf("Duration: %f sec\r\n\r\n", duration);
cout << "Duration: " << duration << " sec"<< endl << endl;
}
return 0;
}
/* Code-End */
当完成上面程序代码并编译执行成功,则你已经有一个全功能的十进制计算器了!
现在就可试试看数万(甚至百万)位数以上的计算能力,但在此之前别忘了使用指令 set
设定环境,至于要怎么做设定请参 set 或 usrenv 指令,但仍注意不要太贪心地设定过
头而导致运算缓慢,使用者得斟酌机器的能耐和需求与时间成本。
祝你编译与使用 Calcl 核心快乐,能找到天堂!
-------------------------------------------------------------------------------
◎ 这个数据夹 calclConstruct 包含 calcl 各组件档案:
目前标头档:calclMainHead.h (calcl 必备基础定义文件,含许多公用标头文件),
Lcalc_base.h (calcl 运算基础函式,非字符串函式),
Lcalc.h (calcl 运算进阶类别 0 代,非字符串类别方法),
L1calc.h (calcl 运算进阶类别 1 代与字符串相关函式),
calclKNL.h (calcl 运算字符串处理接口类别-接洽转化字符串),
calclCombine.h (calcl 标头档结合引入档)。
目前实作档:Lcalc_base.cpp,
Lcalc.cpp,
L1calc.cpp,
calclKNL.cpp,
calclCombine.cpp (calcl 实作档结合引入档)。
发展时间: ↓Lcalc_base.h (最早 200303xx,陆续更新中)
↓Lcalc.h (陆续更新中)
↓L1calc.h (陆续更新中)
↓calclKNL.h (最早 20030827,陆续更新中)
↓calclMainHead.h 与 calclCombine.h (最早 20030925,陆续更新中)
发展到 calclKNL 1.0.4.2 之后,将原先各标头档的定义与实作分开,现在起每个标头
檔(.h)的实作都放置在同名的 .cpp 档案,并增加 calclMainHead.h 包含所有必须的
定义与引入档案,最后增加 calclCombine.h 与 calclCombine.cpp 来进行组合 calcl
的各标头档与实作档案;calclCombine.h 与 calclCombine.cpp 里头的引入档案是有
顺序性的:(calclMainHead→) Lcalc_base→ Lcalc→ L1calc→ calclKNL。
使用:引入定义档 #include "...\CalclConstruct\calclCombine.h",并在主函式的
档案里引入实作 #include "...\CalclConstruct\calclCombine.cpp";其中定
义档可任意引入,但实作档案只可在主函式的档案引入。
﹝注:linux 底下路径改用如 ".../CalclConstruct/calclCombine.h"﹞
进阶:如果想单独使用各档案,请确认必要的先前定义与引入档案(包含继承顺序)。
参考 calclCombine.h 的引入顺序,并查看定义 calclMainHead.h。
-------------------------------------------------------------------------------
版本 1.0.2.1 ~ 1.0.4.2 都要包含 calclKNL.h 才能进行 calcl 程序组装。
版本 1.0.4.2 以后必须引入 calclCombine.h 与 calclCombine.cpp;其除了引入改变
外,函式方法与类别宣告等都和以前一样(可参 1.0.4.2 版(含)以前)。
calclCombine.h 仍以 calclKNL.h 为最终引入标头档案,故仍使用 StrCalclKNL 类别
来直接处理 C 字符串的表达式。
-------------------------------------------------------------------------------
◎ 核心 1.0.5.0 版特点:
版本 1.0.5.0 (11/15/2003) 新增函数:
1. Square Root:
sqrt;
2. Inverse Trigonometric Functions:
asin, acos, atan; //asind, acosd, atand;
3. Hyperbolic Functions:
sinh, cosh, tanh; //sinhd, coshd, tanhd;
4. Inverse Hyperbolic Functions:
asinh, acosh, atanh; //asinhd, acoshd, atanhd;
版本 1.0.5.0 改良算法已提升许多函式运算速度非常多,并改进前版少许错误,尤
其是自然对数函式的改良后,亦间接的提升 pow 函式与其它应用到 ln 函式的函式的
速度甚多。
新增遇到函数(含 e, pi)时-可自动加上乘法符号的功能,将更方便输入使用或表达式
表示,且自订变量名称的等级高于遇到的同名函数的名称或一般同样的字符(串),故可
以自订变量名称来覆盖过内建函数或其它符号等等,但不建议这么做,以避免内建功能
丧失。
新增正负值的表示 +|- 或 -|+,通常出现于 [开方根运算] 或 acosh() 中,若加入运
算式中,则 +|- 取正 -,则 -|+ 取负 -,例如: +|-4 == +4 而 -|+3 == -3。
◎ 核心 1.0.5.1 版特点:
新增额外函式 resolve:res() - 对整数进行质因子分解。
改进一些自动加上乘法符号功能。
◎ 核心 1.0.5.3 版特点:
使用动态内存配置,使用者可以经由指令 set:,,, n 配置内存,使得总位数可以
扩增或减少(经由设定 n 值),让程序对内存资源更有效率地应用,各种需求的使用
者亦可达成属于自己的最佳化 calcl 之可能。
直到目前(01/13/2004)我在 Windows XP 里测试 n 值扩增到上数万(数十万位数以上)
都能正常运作!
◎ 核心 1.0.5.4 20040114 版修正:
修正 1.0.5.3 动态内存配置的错误 (因程序造成内存漏洞)。
◎ 核心 1.0.5.4 20040117 版修正:
修正因 Nd 新设计(增快 e, pi 计算)而导致 e, pi 函式错误部分。
修正 Linux 环境中之前无法扩增 n 值至上万(数十万位数)以上的问题。
*******************************************************************************
****** 我准备迎接 Calcl 64-Bit ******
◎ 20040124 另一新核心产生 (运算内容改自核心 1.0.5.4 --> 32\64 bits):
此日 20040125 经 Linux 与 Windows 环境测试并具稳定的新核心 (32\64) 产生。
可自由使用定义来编译成为使用最大整数 INT32 或 __int64 (long long) 的程序,
这是为了移植到 64 位机器前的准备与测试。
系统位定义含 _SYS32 与 _SYS64,若没先期宣告定义则预设为 _SYS64。
目前在 32 位机器测试使用 _SYS64 编译出来的程序其运算速度较 _SYS32 编译出
来的程序慢许多,我猜测是因 CPU 是 32 位的缘故,所以只能用 32 位整数加
以仿真 64 位整数的运算,因此其速度会受限。若能移植到 64 位机器再编译程
式与执行,我觉得计算相同位数的运算速度应该会比 32 位版本的程序快多。
基本上我定义 INT64 和 INT32 是针对 64 位命名的,但目前仍有以下差异:
使用 _SYS32:INT64 ≡ int,目前的 sizeof(int) == sizeof(long) == 4。
INT32 ≡ short,目前的 sizeof(short) == 2。
使用 _SYS64:INT64 ≡ long long (Linux 环境),sizeof(long long) == 8。
INT64 ≡ __int64 (Windows 环境),sizeof(__int64) == 8。
INT32 ≡ int,目前的 sizeof(int) == sizeof(long) == 4。
注:在 C 中,Linux 环境下,型别 long long 打印使用 %Ld。
在 C 中,WIndows 环境下,型别 __int64 打印使用 %I64d。
PS:过农历年这段时间,我反而更积极的处理改进核心码,算是真认真哩!
*******************************************************************************
-------------------------------------------------------------------------------
◎ 如果想要扩增计算功能,例如增加许多公式或数值算法,L1calc.h 与 Lcalc.h 有
现成的函式与类别方法,提供足够的组件可以开发 Big Number 基础运算相关功能。
◎ 关于 calclKNL.h:
使用方法 calclKNL(char *s) ,输入 s,输出也是 s,不用担心规格变换,更不用去
管理型别转换问题,设计者只需去处理输入接口与计算数据取得,接着便可把表达式放
进 calclKNL() 等待结果出炉。
自 20030826 StrCalclKNL 类别建立后,calclKNL() 移入该类别成为它的方法,诸多
原本在 calclKNL.h 里的函式都移入该类别,该类别包含许多数据成员,用以储存
calcl C string 的数字信息等等,呼叫该类别宣告其对象可自动起始一个 calcl 运算
环境,首次该类别建立的 calclKNL 版本为 1.0.3.0。
◎ 最底层的 Lcalc_base.h ,如同她的名字一样是 calcl 运算的架构基础,其中牵涉很
多作者开发的算法,并提供最基本的一些函式,基本上她不需更动原有内容,除非是
有新增的函式加入或作者发现更快的算法则,在那时我就会更新她的版本。
自 2003082x 已更新许多函式程序代码,从 calclKNL 1.0.3.0 后运算速度更提升,特别
是除法函式之速度改良,并对内存使用亦更佳优化。
1.0.4.0 版,已对 Lcalc_base.h 进行相当多的编修,测试情况也很不错。
1.0.4.2 版,在该版本函式运算上可能都没有错误了,速度也更快。
◎ 自 2003082x 更正几个核心 bugs,1.0.3.0 版本增加字符串(calcl 数字型态)信息功能、
L1calc.h 增加时间显示函式、calclKNL() 参数改为 double 传回核心使用时间长度,
使用 calclKNL() 必须使用 StrCalclKNL 宣告的对象。
20030827 顺利将核心发展程序代码 calcl for console 1.0.3.0 从 Windows 移植至
Red Hat 9 Linux,由 KDevelop 编译并执行成功 (以 root 身份)。
到 20030902 后已确定完全可在 Windows 和 Linux 执行,不论身份为管理者或一般使
用者都可以使用;唯 Windows calcl 只有一个 calcl 的暂存目录,所有 Windows 的
calcl 使用者都必须共享 calcl.tmp 目录,亦包含它底下的设定档也只有一份。
解决上述 Windows calcl 暂存目录共享问题,只要将程序复制到使用者自己的家目录
(自己的账号目录),使用时执行家目录的 calcl 便不会与别人共享同样暂存目录;
calcl 会产生一个新的暂存目录在程序所在的路径,而设定值也会被保留在其中。若是
单机个人使用则无此需要。
每个 Linux calcl 使用者会有自己的 calcl 暂存目录:$home/calcl.tmp,所以
calcl 设定值不会被其它 calcl 使用者无意地更动,Linux 所有使用者都可只用同一
个 calcl 程序或复制程序到家目录单独使用亦可。
◎ 重要:
到 1.0.4.0 版后,n 设定 9000 (36000位)时运作也可正常,只是速度相对变得十分
缓慢;对一般计算机而言,求庞大 n 值下的最高精度(m-p)是几乎跑不完的,除非机器
是多 CPU 或多台计算机一起平行运算的,否则建议的 n 值在 P4-1.8G 处理器下最好
定义 <= 2005,而随较好的机器等级或新算法加入而增加。
到 1.0.5.4 版后因动态内存配置方式的加入,可随使用者因应个人机器与需求扩增
或减少 n 值,将更有效率控制使用者的资源,现在计算至数十万或百万位数都已成为
可能。
在 calcMainHead.h 的前处理器定义,包含置换档案路径与设定档案路径与输入字数
限制等,请不要『任意』更动(除非必要),以避免发生问题。
-------------------------------------------------------------------------------
◎ 我的自制算法不会是最快的,但是我会尽量让它越来越好,而如果你是有兴趣研究的
人当可去改写它,让它更快或程序代码更美观,并且若让它更快更好的话也请你寄一份源
码给我学习,谢谢!
-------------------------------------------------------------------------------
2. 设计者是我的朋友张先生,并非我本人,他只是应我要求,给我一个符合我要的软件。
3. 这个 Calculator 很强大,但不是很完美,有意继续 modify 它的人,希望你们成功。
/* README - CALCL 32\64-Bit 核心源码 Version 1.0.5.4 */
-------------------------------------------------------------------------------
※ calcl 核心源码并不纯粹为自由软件,在使用这些源码相关档案之前,请先同意并遵守
作者的以下条件:
0. 基础条件:本源码仅授权于愿意提供助益给所有人类的程序设计者使用。
1. 必须遵守非商业使用的条件(不能涉及帮自己或他人赚钱之行为),必须纯为义务
公益性质。
2. 修改源码后之程序(含执行文件与修改之源码),都必须提供所有人可免费和直接取
得(含取得管道),但我亦准许发行者得收取适当的硬件工本费 (只可涵盖必须的
硬件成本,如 CD、软盘、邮寄费用等),并绝对遵守上述 0. 和 1. 之条件。
3. 不可将本源码改写或应用于破坏或不利他人的软件上。
4. 对于学生或任何研究者不可将本源码用于其作业或论文或研究等等之某一部分;
唯其作业或论文或研究等等的明显处,有清楚书名本源码的出处与作者(含合法
改码者),且确定避免不当得利者可除外(不当利益含成绩、金钱、任何名利作用
等)。
5. 若违反上述任一条件则视为侵权,作者(含支持上述条件的其它合法改码者)将有
权利控告你的侵权行为,并可因之要求提出赔偿。
6. 知识与技术的取得在理想上应属于自由的层面,必须开放给全人类一起分享,我
提供 Calcl 核心是立于此基础之上的,所有使用 Calcl 核心的程序设计人都应
该知道并遵守这一点;但本人仍同意对于非运算技术相关部分的程序代码,比如介
面环境设计或其它不重要的部分,所有使用到 Calcl 核心的设计者可以保留权
利去决定对该部分源码公开与否,而判别这部分可私藏的源码必须遵守与根据于
以下的规则:
<1> 该源码是设计者的个人特色而无关 Calcl 运算技术。
<2> 缺少该部分源码并不会造成问题,或该源码是具有因人而异的可替代性质而
属于大众皆可制作的独立部分。
由上知道只要你是修改了 Calcl 核心码都必须遵守上述各项规定来公开你的新
版 Calcl 核心码,而假如制作像是主函式 main() 来跑 Calcl 核心应用的源码
这部分,你则可以在不涉及更动 Calcl 核心码的情况下决定该部分源码要公开
或否。
但无论你的私藏源码公开与否,所有 Calcl 核心编程者都至少必须针对一般大
众公开、免费的提供你的程序的可执行文件于网络上或其它可轻易取得的管道,以
造福人群。
- 如果你不愿同意上述者,请马上删除 Calcl 核心码档案不要使用它,以免触法。
- 如果你同意并遵守这些条件限制,即刻起你成为本源码的合法使用者,欢迎改码助益社
会大众,谢谢!
- Copyright (C) 2003-2004 张岑宇 cty personal
-------------------------------------------------------------------------------
使用简体中文者请注意:
由于作者本人从小就是繁体中文的背景,故我的核心源码里的中文字亦属之;对使用简体
中文的人士而言,在编译 Calcl 核心源码之前请先使用翻译软件将各源码档案的繁体中
文字转成简体中文字,以利进行你的程序开发。
-------------------------------------------------------------------------------
我目前使用的 IDE 开发环境编译器是 Dev-C++ 4.9.8.1,这些源码在这个编译器上可成
功编译,并可在 Fedora Core 1 / Mandrake 9.2 的 KDE 的 KDevelop 编译成功。
本核心码数据夹不含主函式﹝如 main()﹞的档案,只有包含 calcl 运算核心档案,程序
员必须自行撰写主函式来应用 Calcl 核心码到你的程序里,在使用 calcl 核心之前得引
入档案 calclCombine.h 与 calclCombine.cpp,且必须宣告 StrCalclKNL 类别的对象并
使用之才可生效。
-------------------------------------------------------------------------------
- 参考码﹝非绝对﹞:
先用整合型编译器(如 Dev-C++)设立项目 Project,并放置档案在一个专用的数据夹内,
接着请将取得的核心源码 CalclConstruct 资料夹也复制到该数据夹内。
﹝为增加编译完成后的程序运算速度,请选择各编译器的最佳化(speed)﹞
﹝用 Dev-C++ 的提升速度:项目→项目选项→编译器讯息→细部最佳化和高度最佳化﹞
开始做程序代码,请开新档案(含有主函式的 cpp 档案),假设取名为 main.cpp 的主函式
档案,参考内容若下:
/*
** main() -- 示范在 Windows 操作系统的 Console 使用 calcl 核心码
**
** Copyright (C) 2003-2004 张岑宇 cty personal
**
** Chang, Tsern-Yeu <ciqzi2r5@ms77.hinet.net>
*/
#define __DEBUG 0 //1:包含核心部分除错叙述(in terminal),0:正式版
#define _SYS32 //定义 32-Bit 系统,另一选择(预设) 64-Bit: _SYS64
/* 以下三行定义(#define)是必须的所以不可漏掉 */
#define OPERATIONSYS 2 //定义操作系统 2:Windows,1:Linux
#define GUI 0 //定义图形接口 0:无
#define PROGRAMNAME "calcl" //定义你的程序名称,关系交换用暂存目录名称(重要)
/*
** 在这里(Windows 环境)引入 calcl 核心码(含定义与实作)
**
** 定义文件里包含许多公用标头文件,不必再额外引入下列档案:
**
** <iomanip> <iostream> <cstdio> <cstdlib> <cmath> <ctime>
** <sys/types.h> <sys/stat.h> ...
**
** Linux :<fcntl.h> <unistd.h> ...
** Windows:<windows.h> <io.h> <direct.h> <conio.h> ...
**
** 注:<1>在 Linux 的路径里请使用 '/' 来取代下面的 '\'
** <2>视情况在必要时给予完整的 calcl 核心码所在路径
*/
#include "Calcl64ConstructDynamic\calclCombine.h" //引入定义
#include "Calcl64ConstructDynamic\calclCombine.cpp" //引入实作
/*
** 函式开始前必须了解:
**
** n, m, LP_preci 是全域变量宣告在 Lcalc_base.cpp 里
**
** n :决定运算值总位数,亦配置储存数值的内存的大小
** m :小数字所在元素(小数点右边第一位所在),区隔数值的整数与小数
** LP_preci:最小精度位所在元素,是计算到最小的小数字数所在
**
** n, m, LP_preci 完全控制 StrCalclKNL 类别的对象,所以很重要
**
** 编译连结产生执行档后,在执行期可用核心 set 指令设定 n, m, LP_preci
**
** 总位数在 32-Bit = 4 * n 位
** 总位数在 64-Bit = 8 * n 位
**
** 若欲设定精度者必须注意范围:n - 2 > m > LP_preci > 0
*/
int main()
{
/*
** 这里宣告 StrCalclKNL 类别的对象
** 这对象会产生:交换用暂存目录、环境设定文件、执行期间的运算用交换档案等
*/
StrCalclKNL SCK; //宣告 StrCalclKNL 类别的对象 SCK
double duration; //记录核心(进入到离开)的运算时间(秒)
system("CLS"); //清除 Console 屏幕,Linux 用 system("clear");
while(true)
{
//指示输入,亦可使用 printf("Input: ");
cout << "Input: ";
//读入表达式的字符串,亦可使用 scanf("%s", SCK.Str);
//注意 cin 或 scanf() 不能读入空格,但换 gets() 则可以
cin >> SCK.Str;
//若读入 q ,则结束循环
if(SCK.Str[0] == 'q' && SCK.Str[1] == '\0') break;
//进入运算里
SCK.calclKNL(duration);
//印出答案,亦可使用 printf("Anser: %s\r\n", SCK.Str);
cout << "Anser: "<< SCK.Str << endl;
//印出花费时间,亦可使用 printf("Duration: %f sec\r\n\r\n", duration);
cout << "Duration: " << duration << " sec"<< endl << endl;
}
return 0;
}
/* Code-End */
当完成上面程序代码并编译执行成功,则你已经有一个全功能的十进制计算器了!
现在就可试试看数万(甚至百万)位数以上的计算能力,但在此之前别忘了使用指令 set
设定环境,至于要怎么做设定请参 set 或 usrenv 指令,但仍注意不要太贪心地设定过
头而导致运算缓慢,使用者得斟酌机器的能耐和需求与时间成本。
祝你编译与使用 Calcl 核心快乐,能找到天堂!
-------------------------------------------------------------------------------
◎ 这个数据夹 calclConstruct 包含 calcl 各组件档案:
目前标头档:calclMainHead.h (calcl 必备基础定义文件,含许多公用标头文件),
Lcalc_base.h (calcl 运算基础函式,非字符串函式),
Lcalc.h (calcl 运算进阶类别 0 代,非字符串类别方法),
L1calc.h (calcl 运算进阶类别 1 代与字符串相关函式),
calclKNL.h (calcl 运算字符串处理接口类别-接洽转化字符串),
calclCombine.h (calcl 标头档结合引入档)。
目前实作档:Lcalc_base.cpp,
Lcalc.cpp,
L1calc.cpp,
calclKNL.cpp,
calclCombine.cpp (calcl 实作档结合引入档)。
发展时间: ↓Lcalc_base.h (最早 200303xx,陆续更新中)
↓Lcalc.h (陆续更新中)
↓L1calc.h (陆续更新中)
↓calclKNL.h (最早 20030827,陆续更新中)
↓calclMainHead.h 与 calclCombine.h (最早 20030925,陆续更新中)
发展到 calclKNL 1.0.4.2 之后,将原先各标头档的定义与实作分开,现在起每个标头
檔(.h)的实作都放置在同名的 .cpp 档案,并增加 calclMainHead.h 包含所有必须的
定义与引入档案,最后增加 calclCombine.h 与 calclCombine.cpp 来进行组合 calcl
的各标头档与实作档案;calclCombine.h 与 calclCombine.cpp 里头的引入档案是有
顺序性的:(calclMainHead→) Lcalc_base→ Lcalc→ L1calc→ calclKNL。
使用:引入定义档 #include "...\CalclConstruct\calclCombine.h",并在主函式的
档案里引入实作 #include "...\CalclConstruct\calclCombine.cpp";其中定
义档可任意引入,但实作档案只可在主函式的档案引入。
﹝注:linux 底下路径改用如 ".../CalclConstruct/calclCombine.h"﹞
进阶:如果想单独使用各档案,请确认必要的先前定义与引入档案(包含继承顺序)。
参考 calclCombine.h 的引入顺序,并查看定义 calclMainHead.h。
-------------------------------------------------------------------------------
版本 1.0.2.1 ~ 1.0.4.2 都要包含 calclKNL.h 才能进行 calcl 程序组装。
版本 1.0.4.2 以后必须引入 calclCombine.h 与 calclCombine.cpp;其除了引入改变
外,函式方法与类别宣告等都和以前一样(可参 1.0.4.2 版(含)以前)。
calclCombine.h 仍以 calclKNL.h 为最终引入标头档案,故仍使用 StrCalclKNL 类别
来直接处理 C 字符串的表达式。
-------------------------------------------------------------------------------
◎ 核心 1.0.5.0 版特点:
版本 1.0.5.0 (11/15/2003) 新增函数:
1. Square Root:
sqrt;
2. Inverse Trigonometric Functions:
asin, acos, atan; //asind, acosd, atand;
3. Hyperbolic Functions:
sinh, cosh, tanh; //sinhd, coshd, tanhd;
4. Inverse Hyperbolic Functions:
asinh, acosh, atanh; //asinhd, acoshd, atanhd;
版本 1.0.5.0 改良算法已提升许多函式运算速度非常多,并改进前版少许错误,尤
其是自然对数函式的改良后,亦间接的提升 pow 函式与其它应用到 ln 函式的函式的
速度甚多。
新增遇到函数(含 e, pi)时-可自动加上乘法符号的功能,将更方便输入使用或表达式
表示,且自订变量名称的等级高于遇到的同名函数的名称或一般同样的字符(串),故可
以自订变量名称来覆盖过内建函数或其它符号等等,但不建议这么做,以避免内建功能
丧失。
新增正负值的表示 +|- 或 -|+,通常出现于 [开方根运算] 或 acosh() 中,若加入运
算式中,则 +|- 取正 -,则 -|+ 取负 -,例如: +|-4 == +4 而 -|+3 == -3。
◎ 核心 1.0.5.1 版特点:
新增额外函式 resolve:res() - 对整数进行质因子分解。
改进一些自动加上乘法符号功能。
◎ 核心 1.0.5.3 版特点:
使用动态内存配置,使用者可以经由指令 set:,,, n 配置内存,使得总位数可以
扩增或减少(经由设定 n 值),让程序对内存资源更有效率地应用,各种需求的使用
者亦可达成属于自己的最佳化 calcl 之可能。
直到目前(01/13/2004)我在 Windows XP 里测试 n 值扩增到上数万(数十万位数以上)
都能正常运作!
◎ 核心 1.0.5.4 20040114 版修正:
修正 1.0.5.3 动态内存配置的错误 (因程序造成内存漏洞)。
◎ 核心 1.0.5.4 20040117 版修正:
修正因 Nd 新设计(增快 e, pi 计算)而导致 e, pi 函式错误部分。
修正 Linux 环境中之前无法扩增 n 值至上万(数十万位数)以上的问题。
*******************************************************************************
****** 我准备迎接 Calcl 64-Bit ******
◎ 20040124 另一新核心产生 (运算内容改自核心 1.0.5.4 --> 32\64 bits):
此日 20040125 经 Linux 与 Windows 环境测试并具稳定的新核心 (32\64) 产生。
可自由使用定义来编译成为使用最大整数 INT32 或 __int64 (long long) 的程序,
这是为了移植到 64 位机器前的准备与测试。
系统位定义含 _SYS32 与 _SYS64,若没先期宣告定义则预设为 _SYS64。
目前在 32 位机器测试使用 _SYS64 编译出来的程序其运算速度较 _SYS32 编译出
来的程序慢许多,我猜测是因 CPU 是 32 位的缘故,所以只能用 32 位整数加
以仿真 64 位整数的运算,因此其速度会受限。若能移植到 64 位机器再编译程
式与执行,我觉得计算相同位数的运算速度应该会比 32 位版本的程序快多。
基本上我定义 INT64 和 INT32 是针对 64 位命名的,但目前仍有以下差异:
使用 _SYS32:INT64 ≡ int,目前的 sizeof(int) == sizeof(long) == 4。
INT32 ≡ short,目前的 sizeof(short) == 2。
使用 _SYS64:INT64 ≡ long long (Linux 环境),sizeof(long long) == 8。
INT64 ≡ __int64 (Windows 环境),sizeof(__int64) == 8。
INT32 ≡ int,目前的 sizeof(int) == sizeof(long) == 4。
注:在 C 中,Linux 环境下,型别 long long 打印使用 %Ld。
在 C 中,WIndows 环境下,型别 __int64 打印使用 %I64d。
PS:过农历年这段时间,我反而更积极的处理改进核心码,算是真认真哩!
*******************************************************************************
-------------------------------------------------------------------------------
◎ 如果想要扩增计算功能,例如增加许多公式或数值算法,L1calc.h 与 Lcalc.h 有
现成的函式与类别方法,提供足够的组件可以开发 Big Number 基础运算相关功能。
◎ 关于 calclKNL.h:
使用方法 calclKNL(char *s) ,输入 s,输出也是 s,不用担心规格变换,更不用去
管理型别转换问题,设计者只需去处理输入接口与计算数据取得,接着便可把表达式放
进 calclKNL() 等待结果出炉。
自 20030826 StrCalclKNL 类别建立后,calclKNL() 移入该类别成为它的方法,诸多
原本在 calclKNL.h 里的函式都移入该类别,该类别包含许多数据成员,用以储存
calcl C string 的数字信息等等,呼叫该类别宣告其对象可自动起始一个 calcl 运算
环境,首次该类别建立的 calclKNL 版本为 1.0.3.0。
◎ 最底层的 Lcalc_base.h ,如同她的名字一样是 calcl 运算的架构基础,其中牵涉很
多作者开发的算法,并提供最基本的一些函式,基本上她不需更动原有内容,除非是
有新增的函式加入或作者发现更快的算法则,在那时我就会更新她的版本。
自 2003082x 已更新许多函式程序代码,从 calclKNL 1.0.3.0 后运算速度更提升,特别
是除法函式之速度改良,并对内存使用亦更佳优化。
1.0.4.0 版,已对 Lcalc_base.h 进行相当多的编修,测试情况也很不错。
1.0.4.2 版,在该版本函式运算上可能都没有错误了,速度也更快。
◎ 自 2003082x 更正几个核心 bugs,1.0.3.0 版本增加字符串(calcl 数字型态)信息功能、
L1calc.h 增加时间显示函式、calclKNL() 参数改为 double 传回核心使用时间长度,
使用 calclKNL() 必须使用 StrCalclKNL 宣告的对象。
20030827 顺利将核心发展程序代码 calcl for console 1.0.3.0 从 Windows 移植至
Red Hat 9 Linux,由 KDevelop 编译并执行成功 (以 root 身份)。
到 20030902 后已确定完全可在 Windows 和 Linux 执行,不论身份为管理者或一般使
用者都可以使用;唯 Windows calcl 只有一个 calcl 的暂存目录,所有 Windows 的
calcl 使用者都必须共享 calcl.tmp 目录,亦包含它底下的设定档也只有一份。
解决上述 Windows calcl 暂存目录共享问题,只要将程序复制到使用者自己的家目录
(自己的账号目录),使用时执行家目录的 calcl 便不会与别人共享同样暂存目录;
calcl 会产生一个新的暂存目录在程序所在的路径,而设定值也会被保留在其中。若是
单机个人使用则无此需要。
每个 Linux calcl 使用者会有自己的 calcl 暂存目录:$home/calcl.tmp,所以
calcl 设定值不会被其它 calcl 使用者无意地更动,Linux 所有使用者都可只用同一
个 calcl 程序或复制程序到家目录单独使用亦可。
◎ 重要:
到 1.0.4.0 版后,n 设定 9000 (36000位)时运作也可正常,只是速度相对变得十分
缓慢;对一般计算机而言,求庞大 n 值下的最高精度(m-p)是几乎跑不完的,除非机器
是多 CPU 或多台计算机一起平行运算的,否则建议的 n 值在 P4-1.8G 处理器下最好
定义 <= 2005,而随较好的机器等级或新算法加入而增加。
到 1.0.5.4 版后因动态内存配置方式的加入,可随使用者因应个人机器与需求扩增
或减少 n 值,将更有效率控制使用者的资源,现在计算至数十万或百万位数都已成为
可能。
在 calcMainHead.h 的前处理器定义,包含置换档案路径与设定档案路径与输入字数
限制等,请不要『任意』更动(除非必要),以避免发生问题。
-------------------------------------------------------------------------------
◎ 我的自制算法不会是最快的,但是我会尽量让它越来越好,而如果你是有兴趣研究的
人当可去改写它,让它更快或程序代码更美观,并且若让它更快更好的话也请你寄一份源
码给我学习,谢谢!
-------------------------------------------------------------------------------
/* ** Lcalc_base.cpp -- by 張岑宇 cty personal ** Copyright (C) 2003-2004 張岑宇 cty personal ** 台灣宜蘭縣羅東鎮東安里中山路 2 段 438 號,電話 : 039532913 ** email : ciqzi2r5@ms77.hinet.net ** ciqzi2r5@yahoo.com.tw ** 20040125 ** ** 元素[n]: 大於0表示錯誤碼,0正值,-1負數,-2二進位負數,-3表+|-取+,-4表-|+取- */ #ifdef OPERATIONSYS // n : 頂位元素 , 第 n 位儲存 + (by 0000) or - (by -0001) 表示正負 ; // n 最少要等於 4 , 此處為原始碼則設定為至少 6。 // n 若加大則資源會使用更多且運算時間必須更久 , 機器越好則越快。 static INT64 n = 2005;//預設 static INT64 M = n + 1;//INT32 陣列全長 static INT64 INPUTMAX = INPUTMAX_LIMIT;//預設:INPUTMAX_LIMIT,輸入字元數(bytes)限制:INPUTMAX - 3 static INT64 m = n / 2;//INT32 [] 小數第一位預設值,m 必需大於 0,m 必須小於等於 M-4,1 < m <= M-4 /* ** 下面的 LP_preci 變數 : ** LP_preci : 精度位置 ** : 小數點後 精度所在四位 的位置 == LP_preci 為準確四位, ** LP_preci 必須小於 m 且大於等於 1; ** 其後四位數可能含有誤差值(最末端值), 即 LP_preci-1 為誤差四位的元素。 ** 經內部函式反覆運算後,其誤差可能達小數末 8 位,即 LP_preci 所在。 ** 預設值 m-m/2 : 1 <= m-m/2 < m */ static INT64 LP_preci = m - 10;//精度標位預設值 static INT64 Nd = m - LP_preci + 3;// for L_E0() and L_PI() : 計算 e 及 PI 值的 INT32 [] 陣列大小 /* 以下數個變數用來儲放固定常數值(無限小數),增加運算速度 */ static INT32 *oTEN; //存放 Ln(10) 的值,加速對數運算用 static INT32 *oE0; //存放 常數 e 的值,加速運算用 static INT32 *oPI; //存放 常數 pi 的值,加速運算用 static INT64 oM = 0; //INT32 陣列全長備份 //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* 實作基礎 Calcl 函式 --- C 函式 ------------------------------------------- */ void LBasicEnvVariables()//基礎環境值 { if(n < 4) n = 4; if(n - 3 < m) n = m + 3; if(LP_preci >= m) LP_preci = m - 1; M = n + 1; Nd = m - LP_preci + 3; } bool LIsIntThreeResolved(const INT32 *N)//分析整數是否有 3 的因子,有傳回 1 { INT32 num1, num2; INT64 i, sum = 0; if((i = Lnonzero_first(N)) < m + 1) return 0; for(; i > m; --i) { #ifdef _SYS64 num2 = N[i]; sum += (INT64)(num1 = num2 / 10000000), sum += (INT64)(num1 = ((num2 -= num1 * 10000000) / 1000000)), sum += (INT64)(num1 = ((num2 -= num1 * 1000000) / 100000)), sum += (INT64)(num1 = ((num2 -= num1 * 100000) / 10000)), sum += (INT64)(num1 = ((num2 -= num1 * 10000) / 1000)), sum += (INT64)(num1 = ((num2 -= num1 * 1000) / 100)), sum += (INT64)(num1 = ((num2 -= num1 * 100) / 10)), sum += (INT64)(num2 -= num1 * 10); #else sum += (INT64)(num1 = N[i] / 1000), sum += (INT64)(num2 = (N[i] - (num1 *= 1000)) / 100), sum += (INT64)(num2 = (N[i] - (num1 += (num2 * 100))) / 10), sum += (INT64)(N[i] - num1 - num2 * 10); #endif } if(sum % 3 == 0) return 1;//3 的倍數 return 0;//非 3 的倍數 } bool LIsUpperUnderIntResolved(const INT32 *N, INT64 Dbound, INT64 Ubound)//分析整數是否有 Dbound ~ Ubound 的整數因子(K 最大到 +-Ubound),有傳回 1 { INT64 i, start = Lget_first(N), x; unsigned INT64 S = 0, D; if(Dbound < 0) Dbound *= -1; if(Ubound < 0) Ubound *= -1; if(Dbound > Ubound) i = Dbound, Dbound = Ubound, Ubound = i; #ifdef _STYS64 if((i = Lget_last(N)) < m || (i == m && N[m] > 0) || Ubound > 999999999999 || Ubound == 0) return 0; #else if((i = Lget_last(N)) < m || (i == m && N[m] > 0) || Ubound > 999999 || Ubound == 0) return 0; #endif for(i = start + 1; i >= 0; i--) { D = (INT64)N[i] + S; x = (INT64)(D / Dbound); S = (D % Dbound) * _I10000; if(x > 0 && i <= m) { if(++Dbound > Ubound) return 0;//不是 Dbound ~ Ubound 的倍數 else x = 0, D = S = 0, i = start + 2; } else if(x == 0 && i == m) return 1;//是 Dbound ~ Ubound 的倍數 } return 0;//不是 Dbound ~ Ubound 的倍數 } bool LIsIntResolved(const INT32 *N, INT64 K)//分析整數是否有 K 因子(K 最大到 +-K),有傳回 1 { INT64 i, start = Lget_first(N), x; unsigned INT64 S = 0, D; if(K < 0) K *= -1; #ifdef _STYS64 if((i = Lget_last(N)) < m || (i == m && N[m] > 0) || K > 999999999999 || K == 0) return 0; #else if((i = Lget_last(N)) < m || (i == m && N[m] > 0) || K > 999999 || K == 0) return 0; #endif for(i = start + 1; i >= 0; i--) { D = (unsigned INT64)N[i] + S; x = (unsigned INT64)(D / K); S = (D % K) * _I10000; if(x > 0 && i <= m) return 0;//不是 K 的倍數 else if(x == 0 && i == m) return 1;//是 K 的倍數 } return 0;//不是 K 的倍數 } void initEnvValues()//起始環境數 { if(oM != M) { oM = M; LBasicEnvVariables();//基礎環境值 /* ** 起始固定的全域常數儲放區 oTEN[], oPI[], oE0[] */ delete [] oPI; delete [] oE0; delete [] oTEN; oPI = new INT32 [M]; oE0 = new INT32 [M]; oTEN = new INT32 [M]; } /* ** 輸入字元數(bytes)限制:INPUTMAX - 3 */ #ifdef _SYS64 if(INPUTMAX < (10 * M + 3)) INPUTMAX = (10 * M + 3);//避免輸入字元數限制太小,導致錯誤 else if(INPUTMAX > (40 * M + 3)) INPUTMAX = (40 * M + 3);//避免輸入字元數限制太大,浪費記憶體 #else if(INPUTMAX < (5 * M + 3)) INPUTMAX = (5 * M + 3);//避免輸入字元數限制太小,導致錯誤 else if(INPUTMAX > (20 * M + 3)) INPUTMAX = (20 * M + 3);//避免輸入字元數限制太大,浪費記憶體 #endif if(INPUTMAX < INPUTMAX_LIMIT) INPUTMAX = INPUTMAX_LIMIT;//避免輸入字元數限制小於保護限制,導致錯誤 //for(INT64 i = 0; i < M; ++i) oPI[i] = oE0[i] = oTEN[i] = 0;//起始 oPI[] 與 oE0[] 與 oTEN[] Lzero(oPI), Lzero(oE0), Lzero(oTEN); } void deleteConstants()//刪除固定的全域常數儲放區 oTEN[], oPI[], oE0[] { delete [] oPI; delete [] oE0; delete [] oTEN; } bool LModLastAns(INT32 *Ans)//20030905 new add - 處理結果進位,用在 L_IntMatrixToStr() 裡 { const INT64 LP_UpCheck = LP_preci - 2; if(LP_preci - 2 >= 0)//永遠執行這個 { INT64 i = LP_preci - 2, k; while(Ans[i] == 0) { if(i == LP_UpCheck) return 1; ++i; } k = i; if(Ans[i] >= _I5000 && i <= LP_UpCheck)//末位大於等於五則進位 { ++i; while((Ans[i] += 1) > _I9999 && i < n) { Ans[i] = 0, ++i; } if(i == n) return 0; } if(k <= LP_UpCheck) for(; k >= 0; --k) Ans[k] = 0; } return 1; } void L_point_right_to0(INT32 *R)//小數點右方全部變為 0 { for(INT64 i = m; i >= 0; --i) R[i] = 0; } void L_point_left_to0(INT32 *L)//小數點左方全部變為 0 { for(INT64 i = m + 1; i < n; ++i) L[i] = 0; } INT32 Llog10(const INT32 *X0, INT32 *Ans)//以十為底數之對數 { INT64 i, SaveLP = LP_preci; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; if((i = Lln(X0, Ans)) > 0) { LP_preci = SaveLP; return i; } INT32 *ten; ten = new INT32 [M]; Lln_ten(ten); Lquotient(Ans, ten, Ans); LP_preci = SaveLP; delete [] ten; return 0; } bool Ltan_rad(INT32 *X0, INT32 *Ans)//Tan(x)函數 : x 使用弧度 Rad { INT64 SaveLP = LP_preci; INT32 *Xs; Xs = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lsin_rad(X0, Xs); Lcos_rad(X0, Ans); Lquotient(Xs, Ans, Ans); LP_preci = SaveLP; delete [] Xs; return 0; } bool Ltan_deg(INT32 *X0, INT32 *Ans)//Tan(x)函數 : x 使用角度 Deg { INT64 SaveLP = LP_preci; INT32 *Xs; Xs = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lsin_deg(X0, Xs); Lcos_deg(X0, Ans); Lquotient(Xs, Ans, Ans); LP_preci = SaveLP; delete [] Xs; return 0; } bool Lsin_deg(INT32 *X0, INT32 *Ans)//Sin(x)函數 : x 使用角度 Deg { Ldeg_to_rad(X0, Ans); Lsin_rad(Ans, Ans); return 0; } bool Lcos_deg(INT32 *X0, INT32 *Ans)//Cos(x)函數 : x 使用角度 Deg { Ldeg_to_rad(X0, Ans); Lcos_rad(Ans, Ans); return 0; } void Ladjust_deg(INT32 *D, INT32 *DN)//調整角度 Deg 至 0 ~ 360 的範圍 { INT64 i, tmpLP = LP_preci; INT32 *Xt, *X; Xt = new INT32 [M]; X = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(D, DN), Lzero(X), X[m+1] = 360; if(DN[n] == 0) { Lquotient(DN, X, Xt); if(Lnonzero_first(Xt) >= m + 1) { for(i = m; i >= 0; --i) Xt[i] = 0; Lproduct(X, Xt, X); Lminus(DN, X, DN); } } else if(DN[n] == -1) { Lquotient(DN, X, Xt); Xt[n] = 0; Lone_plus(Xt); for(i = m; i >= 0; --i) Xt[i] = 0; Lproduct(X, Xt, X); Lplus(DN, X, DN); } LP_preci = tmpLP; delete [] Xt; delete [] X; } void Lrad_to_deg(INT32 *R, INT32 *D)//弧度變換至角度 { INT64 SaveLP = LP_preci; INT32 *T, *p; T = new INT32 [M]; p = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Ladjust_rad(R, T); Lzero(D), D[m+1] = 180; L_PI(p); Lquotient(D, p, D); Lproduct(T, D, D); LP_preci = SaveLP; delete [] T; delete [] p; } void Ldeg_to_rad(INT32 *D, INT32 *R)//角度變換至弧度 { INT64 SaveLP = LP_preci; INT32 *T; T = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Ladjust_deg(D, T); L_PI(R); Ldiv_long(R, 180, R); Lproduct(T, R, R); LP_preci = SaveLP; delete [] T; } void Ladjust_rad(INT32 *R, INT32 *RN)//調整弧度 Rad 至 0 ~ 2PI 的範圍 { INT64 i, tmpLP = LP_preci; INT32 *Xt, *X; Xt = new INT32 [M]; X = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(R, RN), L_PI(X), Lplus(X, X, X); if(RN[n] == 0) { Lquotient(RN, X, Xt); if(Lnonzero_first(Xt) >= m + 1) { for(i = m; i >= 0; --i) Xt[i] = 0; Lproduct(X, Xt, X); Lminus(RN, X, RN); } } else if(RN[n] == -1) { Lquotient(RN, X, Xt); Xt[n] = 0; Lone_plus(Xt); for(i = m; i >= 0; --i) Xt[i] = 0; Lproduct(X, Xt, X); Lplus(RN, X, RN); } LP_preci = tmpLP; delete [] Xt; delete [] X; } bool Lcos_rad(INT32 *X0, INT32 *Ans)//Cos(x)函數 : x 使用弧度 Rad { INT64 add_1 = 1, i, SaveLP = LP_preci; INT32 *Xt2, *Xt, *X; Xt2 = new INT32 [M]; Xt = new INT32 [M]; X = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Ladjust_rad(X0, Xt2); for(i = 0; i < M; ++i) Xt[i] = Xt2[i], Ans[i] = 0; Ans[m+1] = 1; Lproduct(Xt, Xt, Xt2); Lcopy(Xt2, X); i = 0; while(1) { ++add_1; if(i == 0) add_1 *= -1, i = 1; else i = 0; Ldiv_long(X, add_1, X); Lplus(X, Ans, Ans); if(add_1 < 0) add_1 *= -1; X[n] = 0, ++add_1; Ldiv_long(X, add_1, X); Lproduct(X, Xt2, X); if(Lnonzero_first(X) <= 0) break;//值為 0 或已到最小 } LP_preci = SaveLP; delete [] Xt2; delete [] Xt; delete [] X; return 0; } bool Lsin_rad(INT32 *X0, INT32 *Ans)//Sin(x)函數 : x 使用弧度 Rad { INT64 add_1 = 0, i, SaveLP = LP_preci; INT32 *Xt2, *Xt, *X; Xt2 = new INT32 [M]; Xt = new INT32 [M]; X = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Ladjust_rad(X0, Xt2); for(i = 0; i < M; ++i) Xt[i] = X[i] = Xt2[i], Ans[i] = 0; Lproduct(Xt, Xt, Xt2); i = 1; while(1) { ++add_1; if(i == 0) add_1 *= -1, i = 1; else i = 0; Ldiv_long(X, add_1, X); Lplus(X, Ans, Ans); if(add_1 < 0) add_1 *= -1; X[n] = 0, ++add_1; Ldiv_long(X, add_1, X); Lproduct(X, Xt2, X); if(Lnonzero_first(X) <= 0) break;//值為 0 或已到最小 } LP_preci = SaveLP; delete [] Xt2; delete [] Xt; delete [] X; return 0; } bool Lsinh(INT32 *X0, INT32 *Ans)//弧(弳)度-sinh { INT64 SaveLP = LP_preci; INT32 *Ez; Ez = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; L_E0(Ez); Lpow(Ez, X0, Ez); Lzero(Ans); Ans[m+1] = 1; Lquotient(Ans, Ez, Ans); Lminus(Ez, Ans, Ans); Ldiv_long(Ans, 2, Ans); LP_preci = SaveLP; delete [] Ez; return 0; } bool Lcosh(INT32 *X0, INT32 *Ans)//弧(弳)度-cosh { INT64 SaveLP = LP_preci; INT32 *Ez; Ez = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; L_E0(Ez); Lpow(Ez, X0, Ez); Lzero(Ans); Ans[m+1] = 1; Lquotient(Ans, Ez, Ans); Lplus(Ez, Ans, Ans); Ldiv_long(Ans, 2, Ans); LP_preci = SaveLP; delete [] Ez; return 0; } bool Ltanh(INT32 *X0, INT32 *Ans)//弧(弳)度-tanh { INT64 SaveLP = LP_preci; INT32 *Ez, *Tmp; Ez = new INT32 [M]; Tmp = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; L_E0(Ez); Lpow(Ez, X0, Ez); Lzero(Ans); Ans[m+1] = 1; Lquotient(Ans, Ez, Ans); Lminus(Ez, Ans, Tmp); Lplus(Ez, Ans, Ans); Lquotient(Tmp, Ans, Ans); LP_preci = SaveLP; delete [] Ez; delete [] Tmp; return 0; } bool Lsinhd(INT32 *X0, INT32 *Ans)//角度-sinhd { Ldeg_to_rad(X0, Ans); Lsinh(Ans, Ans); return 0; } bool Lcoshd(INT32 *X0, INT32 *Ans)//角度-coshd { Ldeg_to_rad(X0, Ans); Lcosh(Ans, Ans); return 0; } bool Ltanhd(INT32 *X0, INT32 *Ans)//角度-tanhd { Ldeg_to_rad(X0, Ans); Ltanh(Ans, Ans); return 0; } bool Lasinh(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-asinh { INT64 SaveLP = LP_preci; INT32 *Tmp, *Tmp2; Tmp = new INT32 [M]; Tmp2 = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(X0, Tmp2); Lproduct(X0, X0, Tmp); Lone_plus(Tmp); //Lzero(Ans); //Ans[m] = 5000; //Lpow(Tmp, Ans, Ans); Lsqrt(Tmp, Ans); Lplus(Tmp2, Ans, Ans); Lln(Ans, Ans); LP_preci = SaveLP; delete [] Tmp; delete [] Tmp2; return 0; } bool Lacosh(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-acosh { if(X0[n] == -1 || Lnonzero_first(X0) < m + 1) return 1;//error : acosh INT64 SaveLP = LP_preci; INT32 *Tmp, *Tmp2; Tmp = new INT32 [M]; Tmp2 = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(X0, Tmp2); Lproduct(X0, X0, Tmp); Lone_minus(Tmp); //Lzero(Ans); //Ans[m] = 5000; //if(Lpow(Tmp, Ans, Ans) > 0) if(Lsqrt(Tmp, Ans) > 0) { LP_preci = SaveLP; delete [] Tmp; delete [] Tmp2; return 1;//error : acosh } Lplus(Tmp2, Ans, Ans); /* AND ----> Lminus(Tmp, Ans, Ans) : acosh 含有 +- 二者 */ Lln(Ans, Ans); Ans[n] = -3;// <-- 標記為 +- 兩個答案 : acosh 含有 +- 二者 LP_preci = SaveLP; delete [] Tmp; delete [] Tmp2; return 0; } bool Latanh(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-atanh { INT64 SaveLP = LP_preci; INT32 *Tmp; Tmp = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(X0, Tmp); Lzero(Ans); Ans[m+1] = 1; Lminus(Ans, Tmp, Ans); Lone_plus(Tmp); Lquotient(Tmp, Ans, Ans); if(Ans[n] == -1) { LP_preci = SaveLP; delete [] Tmp; return 1;//error : atanh } Lln(Ans, Ans); Ldiv_long(Ans, 2, Ans); LP_preci = SaveLP; delete [] Tmp; return 0; } bool Lasinhd(INT32 *X0, INT32 *Ans)//Inverse 角度-asinhd { Ldeg_to_rad(X0, Ans); Lasinh(Ans, Ans); return 0; } bool Lacoshd(INT32 *X0, INT32 *Ans)//Inverse 角度-acoshd { Ldeg_to_rad(X0, Ans); if(Lacosh(Ans, Ans) > 0) return 1;//error : acosh return 0; } bool Latanhd(INT32 *X0, INT32 *Ans)//Inverse 角度-atanhd { Ldeg_to_rad(X0, Ans); if(Latanh(Ans, Ans) > 0) return 1;//error : atanh return 0; } void Ltenpow(INT64 D, INT32 *Ans)//將 10 的整數乘方 D 轉換至長數 INT32[] { bool sign = 0; INT64 i = 0; INT32 *TEN, *ONE; TEN = new INT32 [M]; ONE = new INT32 [M]; for(i = 0; i < M; ++i) TEN[i] = ONE[i] = Ans[i] = 0; TEN[m+1] = 10, Ans[m+1] = ONE[m+1] = 1; if(D < 0) sign = 1, D *= -1; for(i = D; i > 0; --i) Lproduct(TEN, Ans, Ans); if(sign == 1) Lquotient(ONE, Ans, Ans); delete [] TEN; delete [] ONE; } INT32 Lsqrt(const INT32 *X0, INT32 *Ans)//集合各開平方根函數, 可處理所有正實數之開平方根 { INT64 L, tmpLP = LP_preci; if(X0[n] != 0 && X0[n] != -3)//不可處理負數 { Ans[n] = 10; return 10; } if(LP_preci - 2 > 1) LP_preci -= 2; else LP_preci = 1; L = Lnonzero_first(X0); if(L<m+1) Lsqt_0to1(X0, Ans); else if(L > m + 1 || (L == m + 1 && X0[m+1] > 10)) Lsqt_up10(X0, Ans); else if(L == m + 1 && X0[m+1] <= 10) Lsqt_1to10(X0, Ans); Ans[n] = -3;//含正負 +|- LP_preci = tmpLP; return 0; } INT32 Lsqt_up10(const INT32 *Num0, INT32 *Ans)//求出 10 < Num 的平方根 { INT64 i, k, t, D = 0; float re = 0; INT32 *Num; Num = new INT32 [M]; Lcopy(Num0, Num); Lzero(Ans); if(Num[n]!=0||(i=Lnonzero_first(Num))<m+1||(i==m+1&&Num[m+1]<11)) { Ans[n]=10; delete [] Num; return 10; } k = i - m - 1, D = 4 * k; #ifdef _SYS64 D *= 2; #endif for(t=0;k>0&&t<=i;++t) { if(t+k<n) Num[t]=Num[t+k]; else Num[t]=0; } #ifdef _SYS64 if(Num[m+1]>9999999) Lright_move(Num,Num), ++D; if(Num[m+1]>999999) Lright_move(Num,Num), ++D; if(Num[m+1]>99999) Lright_move(Num,Num), ++D; if(Num[m+1]>9999) Lright_move(Num,Num), ++D; #endif if(Num[m+1]>999) Lright_move(Num,Num), ++D; if(Num[m+1]>99) Lright_move(Num,Num), ++D; if(Num[m+1]>9) Lright_move(Num,Num), ++D; Lsqt_1to10(Num, Ans);//test str: 5960464477539062500000 re = D, re /= 2, D /= 2, re -= D; if(re == 0.5) { Lzero(Num), Num[m+1] = 10; Lsqt_1to10(Num, Num); Lproduct(Num, Ans, Ans); } if(D != 0) { Ltenpow(D, Num); Lproduct(Num, Ans, Ans); } delete [] Num; return 0; } INT32 Lsqt_0to1(const INT32 *Num0, INT32 *Ans)//求出 0<= Num <=1 的平方根 { INT64 i, k, D = 0; float re = 0; INT32 *Num; Num = new INT32 [M]; Lcopy(Num0, Num); Lzero(Ans); if((i = Lnonzero_first(Num)) > m || Num[n] == -1) { if(i == m + 1 && Num[m+1] == 1 && (k = Lget_last(Num)) == m && Num[m] == 0) { Ans[m+1] = 1; delete [] Num; return 0; } else { Ans[n]=10; delete [] Num; return 10; } } else if(i == -1) { delete [] Num; return 0;//值為0 } k = m - i, D = -4 * k; #ifdef _SYS64 D *= 2; #endif for(i = m; i >= 0 && k > 0; --i) { if(i - k >= 0) Num[i] = Num[i-k]; else Num[i] = 0; } if(Num[m]<10) Lleft_move(Num, Num), --D; if(Num[m]<100) Lleft_move(Num, Num), --D; if(Num[m]<1000) Lleft_move(Num, Num), --D; if(Num[m]<10000) Lleft_move(Num, Num), --D; #ifdef _SYS64 if(Num[m]<100000) Lleft_move(Num, Num), --D; if(Num[m]<1000000) Lleft_move(Num, Num), --D; if(Num[m]<10000000) Lleft_move(Num, Num), --D; if(Num[m]<100000000) Lleft_move(Num, Num), --D; #endif Lsqt_1to10(Num, Ans); re = D, re /= 2, D /= 2, re -= D; if(re == -0.5) { Lzero(Num), Num[m+1] = 10, --D; Lsqt_1to10(Num, Num); Lproduct(Num, Ans, Ans); } if(D != 0) { Ltenpow(D, Num); Lproduct(Num, Ans, Ans); } delete [] Num; return 0; } INT32 Lsqt_1to10(const INT32 *Num0, INT32 *Ans)//求出 1<= Num <=10 的平方根 { INT64 i, p; bool chg = 0; INT32 *T, *A, *Num; T = new INT32 [M]; A = new INT32 [M]; Num = new INT32 [M]; Lcopy(Num0, Num); Lzero(Ans); Lzero(T); Lzero(A); if(Num[m+1] > 10 || Num[n] == -1 || (i = Lnonzero_first(Num)) > m + 1 || i < m + 1) { Ans[n] = 10; delete [] T; delete [] A; delete [] Num; return 10; } else if(Lget_last(Num) == m && Num[m] == 0) { if(Num[m+1] == 0 || Num[m+1] == 1 || Num[m+1] == 4 || Num[m+1] == 9) { if(Num[m+1] == 0) Ans[m+1] = 0; else if(Num[m+1] == 1) Ans[m+1] = 1; else if(Num[m+1] == 4) Ans[m+1] = 2; else Ans[m+1] = 3; delete [] T; delete [] A; delete [] Num; return 0; } } if(Num[m+1] == 1) { chg = 1, A[m+1] = 4; Lproduct(A, Num, Num); } if(Num[m+1] <= 3) A[m+1] = 1; else if(Num[m+1] <= 8) A[m+1] = 2; else if(Num[m+1] <= 10) A[m+1] = 3; INT64 allowerr[2] = {n, 0}; p = 0; while(i > LP_preci && p <= 100) { Lquotient(Num, A, T); Lplus(T, A, T); Ldiv_long(T, 2, Ans); Lproduct(Ans, Ans, T); Lminus(T, Num, T); for(i = m + 1; T[i] == 0 && i >= 0; --i); if(i != -1) { if(i + 1 < allowerr[0] || (i + 1 == allowerr[0] && T[i+1] < allowerr[1])) { allowerr[0] = i + 1, allowerr[1] = T[i+1]; } else if(i + 1 >= allowerr[0] && T[i+1] >= allowerr[1]) { if(++p == 10)//無法收斂的對策 1 { L_E0(T), Lproduct(T, T, T), Lproduct(Num, T, Num); allowerr[0] = i + 1, allowerr[1] = (INT64)T[i+1]; } else if(p == 20)//無法收斂的對策 2 { L_PI(T), Lproduct(T, T, T), Lproduct(Num, T, Num); allowerr[0] = i + 1, allowerr[1] = (INT64)T[i+1]; } } } Lcopy(Ans, A); //LCshowf(Ans);cout << endl;//test str: 5.9604644775390625 } if(p >= 20) L_PI(T), Lquotient(Ans, T, Ans); if(p >= 10) L_E0(T), Lquotient(Ans, T, Ans); if(p >= 100) for(++i; i >= 0; --i) Ans[i] = 0;//收斂不了的最壞處理 if(chg == 1) Ldiv_long(Ans, 2, Ans); delete [] T; delete [] A; delete [] Num; return 0; } bool Lasin_x(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-asin 的內部處理函式 _x { bool ps = 0; INT32 *Xt; Xt = new INT32 [M]; if(X0[n] == -1) ps = 1; Lproduct(X0, X0, Xt); Lzero(Ans); Ans[m+1] = 1; Lminus(Ans, Xt, Xt); //Ans[m+1] = 0, Ans[m] = 5000; //Lpow(Xt, Ans, Ans); Lsqrt(Xt, Ans);//開根方 Lasin_ex(Ans, Ans); L_PI(Xt); Ldiv_long(Xt, 2, Xt); if(ps == 1) Lminus(Ans, Xt, Ans); else Lminus(Xt, Ans, Ans); delete [] Xt; return 0; } bool Lasin(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-asin { INT64 i = 0; bool rtn = 0; INT64 SaveLP = LP_preci; if((i = Lnonzero_first(X0)) > m + 1 || (i == m + 1 && X0[m+1] > 1)) return 1;//error : asin else if(i == m + 1 && X0[m+1] == 1) { if((i = Lget_last(X0)) < m || (i == m && X0[m] > 0)) return 1;//error : asin } else if(i == -1) { Lzero(Ans);//答案 0 return 0; } if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; //下面Lasin_x()主要用於增快接近臨界[-1,1]收斂速度,當 |X0| > 0.999.... 趨近 1 時 #ifdef _SYS64 if(X0[m+1] == 1 || X0[m] > 94000000 || (X0[m] > 71000000 && (i - Lget_last(X0) + 1) >= m - LP_preci)) #else if(X0[m+1] == 1 || X0[m] > 9400 || (X0[m] > 7100 && (i - Lget_last(X0) + 1) >= m - LP_preci)) #endif { rtn = Lasin_x(X0, Ans);//增快接近臨界[-1,1]運算速度 } else { rtn = Lasin_ex(X0, Ans); } LP_preci = SaveLP; return rtn; } bool Lasin_ex(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-asin 的內部處理主函式 _ex { INT64 add_1 = 2; bool sign = 0;//正 INT32 *Xt, *Tmp2; Xt = new INT32 [M]; Tmp2 = new INT32 [M]; Lcopy(X0, Ans); Lproduct(X0, X0, Xt); Lproduct(X0, Xt, Tmp2); if(Ans[n] == -1) sign = 1, Tmp2[n] = Ans[n] = 0; Ldiv_long(Tmp2, 2, Tmp2); while(Lans_asin(Tmp2, ++add_1, Ans) == 0) Ldivmul_asin(Tmp2, ++add_1, Xt); if(sign == 1) Ans[n] = -1; delete [] Xt; delete [] Tmp2; return 0; } bool Lans_asin(INT32 *A0, INT64 b, INT32 *Ans)//加總結果:除加法,供 Lasin_ex() { bool br = 0; INT64 i; unsigned INT64 D, S = 0; INT32 *A, *B; A = new INT32 [M]; B = new INT32 [M]; for(i = m + 1, Lzero(A), Lzero(B); i >= LP_preci - 2 && i >= 0; i--) { D = (INT64)A0[i], A[i] = (INT32)((D + S) / b), S = ((D + S) % b) * _I10000; } Lplus(A, Ans, Ans); Lcopy(A0, A); if(b < _I10000) B[m+1] = b; else if(b < _I10000 * _I10000) B[m+2] = (INT32)(b / _I10000), B[m+1] = (INT32)(b - B[m+2] * _I10000); br = Lmul_asin(A, B, A0); delete [] A; delete [] B; return br; } void Ldivmul_asin(INT32 *Ans, INT64 b, const INT32 *B)//除乘法 : 供 Lasin_ex() { INT64 i; unsigned INT64 D, S = 0; INT32 *A; A = new INT32 [M]; for(i = m + 1, Lzero(A); i >= LP_preci - 2 && i >= 0; i--) { D = (INT64)Ans[i], A[i] = (INT32)((D + S) / b), S = ((D + S) % b) * _I10000; } Lmul_asin(A, B, Ans); delete [] A; } bool Lmul_asin(const INT32 *A, const INT32 *B, INT32 *Ans)//Lasin_ex()的內部乘法 { INT64 i, j, t, I, J, sI, sJ, k, buffer, buffer2; for(i = m + 2, sI = sJ = -1; i >= 0 && (sI == -1 || sJ == -1); --i) { if(sI == -1 && A[i] != 0) sI = i; if(sJ == -1 && B[i] != 0) sJ = i; } if(sI == -1 || sJ == -1) return 1;//完成 asin 運算 for(I = J = -1, i = LP_preci; I == -1 || J == -1; ++i) { if(I == -1 && (A[i] != 0 || i == m)) I = i; if(J == -1 && (B[i] != 0 || i == m)) J = i; } for(Lzero(Ans), j = J; j <= sJ; ++j) { for(i = I, k = i + j - m - 1; B[j] > 0 && i <= sI && k < n; ++i, ++k) { if(k < LP_preci) { i += LP_preci - k - 1, k = LP_preci - 1; continue;//防止小數點末端溢位 } if((buffer = (INT64)A[i] * (INT64)B[j]) > _I9999)//進位及強制型別轉換(INT64 <--- int) , 只讀取整數部分 { buffer2 = buffer; Ans[k+1] += (INT32)(buffer /= _I10000), Ans[k] += (INT32)(buffer2 - (buffer *= _I10000));//強制型別轉換(INT32 <--- long) } else Ans[k] += (INT32)buffer;//強制型別轉換(INT32 <--- long) for(t = k; t < n; ++t)//initial:k = P+j-J { if(Ans[t] > _I9999) Ans[t] -= _I10000, Ans[t+1] += 1; if(t + 1 < M - 2 && Ans[t+1] < _I10000 && Ans[t+2] < _I10000) break; } } } return 0; } bool Lacos(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-acos { if(Lasin(X0, Ans) > 0) return 1;//error : acos INT64 SaveLP = LP_preci; INT32 *Tmp; Tmp = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; L_PI(Tmp); Ldiv_long(Tmp, 2, Tmp); Lminus(Tmp, Ans, Ans); LP_preci = SaveLP; delete [] Tmp; return 0; } bool Latan(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-atan { INT64 SaveLP = LP_preci; INT32 *Xt; Xt = new INT32 [M]; //INT32 *Xf; //Xf = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; //Lzero(Xf); //Xf[m] = 5000; Lcopy(X0, Xt); Lproduct(X0, X0, Ans); Lone_plus(Ans); //Lpow(Ans, Xf, Ans); Lsqrt(Ans, Ans);//開根方 Lquotient(Xt, Ans, Ans); Lasin(Ans, Ans); LP_preci = SaveLP; //delete [] Xf; delete [] Xt; return 0; } /* bool Latan(INT32 *X0, INT32 *Ans)//Inverse 弧(弳)度-atan { INT64 i, SaveLP = LP_preci; INT64 add_1 = 3; INT32 *Tmp, *Xt, *Xp; Tmp = new INT32 [M]; Xt = new INT32 [M]; Xp = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(X0, Ans); Lproduct(X0, X0, Xt); Lproduct(X0, Xt, Xp); if(Xp[n] == -1) Xp[n] = 0; else Xp[n] = -1; Ldiv_long(Xp, 3, Tmp); while(1) { Lplus(Tmp, Ans, Ans); if(Xp[n] == -1) Xp[n] = 0; else Xp[n] = -1; Lproduct(Xt, Xp, Xp); if(Lnonzero_first(Xp) <= 0) break;//最小或已是 0 Ldiv_long(Xp, (add_1 += 2), Tmp); } LP_preci = SaveLP; delete [] Tmp; delete [] Xt; delete [] Xp; return 0; } */ bool Lasind(INT32 *X0, INT32 *Ans)//Inverse 角度-asind : 輸出為角度值 { if(Lasin(X0, Ans) > 0) return 1;//error : asin Lrad_to_deg(Ans, Ans); return 0; } bool Lacosd(INT32 *X0, INT32 *Ans)//Inverse 角度-acosd : 輸出為角度值 { if(Lacos(X0, Ans) > 0) return 1;//error : acos Lrad_to_deg(Ans, Ans); return 0; } bool Latand(INT32 *X0, INT32 *Ans)//Inverse 角度-atand : 輸出為角度值 { Latan(X0, Ans); Lrad_to_deg(Ans, Ans); return 0; } INT32 Lpow(const INT32 *A0, const INT32 *B0, INT32 *Ans)//乘方法 : for all num { INT64 tmp_LP_preci = LP_preci;//暫存精度初值 INT32 sign = A0[n], sign2 = B0[n], bi; INT64 i; bool PandN = 0;//儲存+|-或無,若有則結果Ans[n]記為 -3 INT32 *A, *B, *C; A = new INT32 [M]; B = new INT32 [M]; C = new INT32 [M]; if(LP_preci - 5 >= 1) LP_preci -= 5;//提深精度以避免結果誤差大 else LP_preci = 1; for(i = 0; i < M; ++i) A[i] = A0[i], B[i] = B0[i], Ans[i] = C[i] = 0; if((i = Lnonzero_first(B)) == -1)//結果值為1 { Ans[m+1] = 1; LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; } else if(i <= m && B[Lget_last(B)] % 5 == 0)//判別是否有+|-值 { Ans[m+1] = 2; Lcopy(B, C); while(C[m+1] == 0) Lproduct(Ans, C, C); if(Lget_last(C) == m && C[m] == 0 && C[m+1] == 1) PandN = 1;//標記有+|-值,在本函式末將Ans[n]定為=-3 Lzero(C); Ans[m+1] = 0; } bi=Lget_last(B); if(i == m + 1 && B[i] == 1 && bi == m && B[bi] == 0 && B[n] == 0)//結果值為A0 { Lcopy(A, Ans); LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; } if(Lnonzero_first(A) == -1)//結果值為 0 { LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; } /*//這區塊已除效,因新的 bug 修正後改善 pow 功能,現在觀察中 else if(i < m + 1 && (bi < m || (bi == m && B[bi] > 0)) && A[n] == 0)//本區塊處理(0~1)^(0~1) { i = m - i; Ans[m+2] = 1, C[m+2] = 1; for(; i >= 0; --i) Lproduct(Ans, C, Ans);//計算多少 10000 的乘方 Lproduct(A, Ans, A);//乘上 10000^(?) 倍數(左移) Lpow(A, B, A);//第一個乘方 if(B[n] == 0) B[n] = -1; else if(B[n] <= -1) B[n] = 0; Lpow(Ans, B, Ans);//第二個乘方 Lproduct(A, Ans, Ans);//第一結果乘上第二結果 LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; }*/ /* 這兒:bi == Lget_last(B) */ if((bi < m || (bi == m && B[m] != 0)) && A[n] == -1)//非實數結果 { LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return (Ans[n] = 11); } if(sign == -1 || sign == -4) A[n] = 0; if(sign2 == -1 || sign2 == -4) B[n] = 0; if(bi == m && B[m] == 0)//快速處理整數乘方 B { Ldiv_long(B, 2, C); if(C[m] == 0) sign = 0; Ans[m+1] = 1; while(1) { Lproduct(Ans, A, Ans); Lone_minus(B); if(Lget_first(B) == m + 1 && B[m+1] == 0 || Ans[n] == -1 || Ans[n] > 0) break; } if(Ans[n] == 0) Ans[n] = sign; else { LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return (Ans[n] = 3);//最大位數溢位#3 } if(sign2 == -1) { B[m+1] = 1; Lquotient(B, Ans, Ans); } LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; } Lln(A, A);//導致 Lpow() 最慢的點,我的對數處理還不是最完好狀態 Lproduct(B, A, A); if(sign == -1 || sign == -4) { Ldiv_long(B, 2, B); if(B[m] == 0) sign = 0; } C[m+1] = 1, i = 0; while(i < _I99999999) { Ldiv_long(C, (++i), C); Lproduct(C, A, C); Lplus(C, Ans, Ans); if(Lnonzero_first(C) <= 0 || Ans[n] > 0) break; } if(Ans[n] <= 0)//don't change here { Lone_plus(Ans); Ans[n] = sign; } else { LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return (Ans[n] = 3);//最大位數溢位#3 } if(sign2 == -1 || sign2 == -4) { Lzero(B), B[m+1] = 1; Lquotient(B, Ans, Ans); } if(PandN == 1) Ans[n] = -3;//+|- LP_preci = tmp_LP_preci;//還原精度初值 delete [] A; delete [] B; delete [] C; return 0; } INT32 Ldiv_long(const INT32 *A, INT64 b, INT32 *Ans)//除法 : 供除數 b 為單純之 INT64 INT32 使用, 可加快速度 { INT64 i; INT32 *a; a = new INT32 [M]; unsigned INT64 D, S = 0; if(b == 0) { delete [] a; return (Ans[n] = 4);//除數為0 } #ifdef _SYS64 if(b > 999999999999LL || b < -999999999999LL)//Ldiv_long() 最高整數除數處理位數 #else if(b > 999999 || b < -999999)//Ldiv_long() 最高整數除數處理位數 #endif { Lzero(a); a[m+2] = (INT32)(b / _I10000); a[m+1] = (INT32)(b - (INT64)a[m+2] * _I10000); i = Lquotient(A, a, Ans); delete [] a; return i; } for(i = 0; i < M; i++) a[i] = A[i], Ans[i] = 0; /* 處理+-符號 */ if((a[n] == -1 || a[n] == -4) && b < 0) a[n] = 0, b *= -1; else if((a[n] == -1 || a[n] == -4) && b > 0) a[n] = 0, Ans[n] = -1; else if((a[n] == 0 || a[n] == -3) && b < 0) b *= -1, Ans[n] = -1; if((i = Lnonzero_first(a)) == -1) i = 0; for(; i >= LP_preci - 2 && i >= 0; i--) { D = (INT64)a[i], Ans[i] = (INT32)((D + S) / b), S = ((D + S) % b) * _I10000; } delete [] a; return 0; } bool L_PI(INT32 *E)//快速求 PI 法 { if(oPI[m+1] == 3 && oPI[m+2] == 0)//20030914 新增 { if(Lget_last(oPI) <= LP_preci - 1) { Lcopy(oPI, E); return 0; } } INT32 *P, *Q, *v, *q; P = new INT32 [Nd+2]; Q = new INT32 [Nd+2]; v = new INT32 [Nd+2]; q = new INT32 [Nd+2]; INT64 i, tmpLP = LP_preci; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lzero(E); for(i = 0; i < Nd + 2; ++i)//起始 INT32 [] = 0 { P[i] = Q[i] = v[i] = q[i] = 0; } Q[0] = 80, v[0] = 956;//馬欽公式起始化 i = 0; while(!L_fucs_check(Q)) { L_fucs_quotient(Q, 25, Q), L_fucs_quotient(v, 57121, v),//等於 L_fucs_quotient(v, 239*239, v), L_fucs_minus(Q, v, q), L_fucs_quotient(q, 2*(++i)-1, q); if((i % 2) != 0) L_fucs_plus(P, q, P); else L_fucs_minus(P, q, P); } LP_preci = tmpLP; for(i = m + 1; m - i + 1 < Nd + 2; --i) { E[i] = P[m-i+1]; //P[] 複製到 E[] if(i == LP_preci - 2 || i == 0) break; } delete [] P; delete [] Q; delete [] v; delete [] q; Lcopy(E, oPI); return 0; } bool L_E0(INT32 *E)//快速求 e 法 { if(oE0[m+1] == 2 && oE0[m+2] == 0)//20030914 新增 { if(Lget_last(oE0) <= LP_preci - 1) { Lcopy(oE0, E); return 0; } } INT32 *P, *Q; P = new INT32 [Nd+2]; Q = new INT32 [Nd+2]; INT64 i, tmpLP = LP_preci; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lzero(E); for(i = 0; i < Nd + 2; ++i)//起始 INT32 [] = 0 { P[i] = Q[i] = 0; } P[0] = Q[0] = 1; i = 1; while(!L_fucs_check(Q)) { L_fucs_quotient(Q, i, Q), L_fucs_plus(P, Q, P), ++i; } LP_preci = tmpLP; for(i = m + 1; m - i + 1 < Nd + 2; --i) { E[i] = P[m-i+1]; //P[] 複製到 E[] if(i == LP_preci - 2 || i == 0) break; } delete [] P; delete [] Q; Lcopy(E, oE0); return 0; } bool L_fucs_check(INT32 *C)//for L_E0() & L_PI() { INT64 i; for(i = 0; i < Nd + 2; ++i) { if(i >= (3 + m - LP_preci) && C[i-1] == 0) break; else if(C[i] != 0 && i < Nd + 1) return 0; } if(C[0] == 0) return 1;//確定程式可執行完畢,因已經求出最高精度,傳回 1 else return 0; } void L_fucs_plus(INT32 *A, INT32 *B, INT32 *Ans)//for L_E0() & L_PI() { INT64 i; INT32 t = 0; for(i = Nd; i >= 0; --i) { if((Ans[i] = A[i] + B[i] + t) < _I10000) t = 0; else Ans[i] -= _I10000, t = 1; } } void L_fucs_minus(INT32 *A, INT32 *B, INT32 *Ans)//for L_E0() & L_PI() { INT64 i; INT32 t = 0; for(i = Nd; i >= 0; --i) { if((Ans[i] = A[i] - B[i] - t) >= 0) t = 0; else Ans[i] += _I10000, t = 1; } } void L_fucs_quotient(INT32 *A, INT64 V, INT32 *Ans)//for L_E0() & L_PI() { INT64 i, D, S = 0; for(i = 0; i <= Nd; i++) D = (INT64)A[i], Ans[i] = (INT32)((D + S) / V), S = (( D + S) % V) * _I10000; } INT32 Lln(const INT32 *X0, INT32 *Ans)//new:20031112 - 自然對數 : 求真數大於 0 { INT64 k, Save_LP_preci = LP_preci; INT32 *X; X = new INT32 [M]; if(LP_preci - 2 >= 1) LP_preci -= 2; else LP_preci = 1; Lcopy(X0, X); k = Lnonzero_first(X); if(X[n] == -1 || X[n] == -4 || k == -1)//不可為負值或0 { LP_preci = Save_LP_preci; delete [] X; return (Ans[n] = 9); } Lzero(Ans); if(k == m + 1 && X[m+1] == 1)//真數 : 1 <= X0 < 2 { INT32 *P; P = new INT32 [M]; Lzero(P); if(X[m] >= _I9000) { P[m+1] = 1, P[m] = _I6000; Lquotient(X, P, X); Lln(P, P); } INT32 *S, *T, *D; S = new INT32 [M]; T = new INT32 [M]; D = new INT32 [M]; Lzero(S); Lzero(T); Lzero(D); if(Lget_last(X) <= LP_preci + 2 && X[m] > _I1000) { S[m+1] = 1, S[m] = _I1000, k = 0; while(Lnonzero_first(X) > m) { ++k; Lquotient(X, S, X); } Lproduct(X, S, X); if(--k > 0) { if(k <= _I9999) T[m+1] = k; else if(k <= _I99999999) T[m+2] = (INT32)(k / _I10000), T[m+1] = (INT32)(k - T[m+2] * _I10000); Lln(S, D);//=ln(1.1) Lproduct(T, D, D);//=T*ln(1.1) } S[m] = 0; } X[m+1] = 0, S[m+1] = 1, k = 0; while(1) { if((k *= -1) >= 0) ++k; else --k; Lproduct(X, S, S); Ldiv_long(S, k, T); Lplus(T, Ans, Ans); if(Lnonzero_first(T) <= 0) break;//值已最小或 0 } delete [] S; delete [] T; Lplus(Ans, D, Ans); Lplus(Ans, P, Ans); delete [] D; delete [] P; } else if(k >= m + 1)//真數 : 2 <= X0 { INT64 t = 0; INT32 *Tmp; Tmp = new INT32 [M]; Lzero(Tmp); Tmp[m+2] = 1, Ans[m+1] = 1; for(t = k = k - m - 1; k >= 0; --k) Lproduct(Tmp, Ans, Ans); Lquotient(X, Ans, X); Tmp[m+2] = 0, ++t, t *= 4; #ifdef _SYS64 t *= 2; if(X[m] < 10) t -= 7, Tmp[m+1] = 10000000, Lproduct(Tmp, X, X); else if(X[m] < 100) t -= 6, Tmp[m+1] = 1000000, Lproduct(Tmp, X, X); else if(X[m] < 1000) t -= 5, Tmp[m+1] = 100000, Lproduct(Tmp, X, X); else if(X[m] < 10000) t -= 4, Tmp[m+1] = 10000, Lproduct(Tmp, X, X); else if(X[m] < 100000) t -= 3, Tmp[m+1] = 1000, Lproduct(Tmp, X, X); else if(X[m] < 1000000) t -= 2, Tmp[m+1] = 100, Lproduct(Tmp, X, X); else if(X[m] < 10000000) t -= 1, Tmp[m+1] = 10, Lproduct(Tmp, X, X); #else if(X[m] < 10) t -= 3, Tmp[m+1] = 1000, Lproduct(Tmp, X, X); else if(X[m] < 100) t -= 2, Tmp[m+1] = 100, Lproduct(Tmp, X, X); else if(X[m] < 1000) t -= 1, Tmp[m+1] = 10, Lproduct(Tmp, X, X); #endif Tmp[m+1] = 0; if(t <= _I9999) Tmp[m+1] = t; else if(t <= _I99999999) Tmp[m+2] = (INT32)(t / _I10000), Tmp[m+1] = (INT32)(t - Tmp[m+2] * _I10000); if(oTEN[m+1] == 2 && Lget_last(oTEN) <= LP_preci) { Lcopy(oTEN, Ans);//ln(10) } else { Lzero(oTEN); Lzero(Ans); Ans[m+1] = 4, oTEN[m+1] = 1, oTEN[m] = _I6000;//=4, =1.6 Lln(oTEN, oTEN);//=ln(1.6) Lproduct(oTEN, Ans, oTEN);//=ln(1.6^4)=4*ln(1.6) #ifdef _SYS64 Ans[m+1] = 1, Ans[m] = 52587890, Ans[m-1] = 62500000;//=10/(1.6^4)=1.52587890 62500000 #else Ans[m+1] = 1, Ans[m] = 5258, Ans[m-1] = 7890, Ans[m-2] = 6250;//=10/(1.6^4)=1.5258 7890 6250 #endif Lln(Ans, Ans);//=ln(10/(1.6^4))=ln(1.525878906250); Lplus(Ans, oTEN, Ans);//=ln(10) Lcopy(Ans, oTEN);//ln(10) } Lproduct(Tmp, Ans, Ans);//=ln(10^t)=t*ln(10) delete [] Tmp; Lln(X, X); Lplus(X, Ans, Ans); } else if(k <= m)//真數 : 0 < X0 < 1 { INT32 *P; P = new INT32 [M]; Lzero(P); if(X[m] <= _I1000) { INT32 *Tmp; Tmp = new INT32 [M]; Lzero(Tmp); P[m+1] = 1, Tmp[m+2] = 1; for(k = m - k - 1; k >= 0; --k) Lproduct(Tmp, P, P); //cout << endl; Lproduct(X, P, X); Tmp[m+2] = 0; #ifdef _SYS64 if(X[m] < 10) Tmp[m+1] = 10000000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 100) Tmp[m+1] = 1000000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 1000) Tmp[m+1] = 100000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 10000) Tmp[m+1] = 10000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 100000) Tmp[m+1] = 1000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 1000000) Tmp[m+1] = 100, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 10000000) Tmp[m+1] = 10, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); #else if(X[m] < 10) Tmp[m+1] = 1000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 100) Tmp[m+1] = 100, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); else if(X[m] < 1000) Tmp[m+1] = 10, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); #endif if(X[m] == _I1000) Tmp[m+1] = 9, Tmp[m] = _I9000, Lproduct(Tmp, X, X), Lproduct(Tmp, P, P); delete [] Tmp; Lln(P, P); } INT32 *S, *T, *D; S = new INT32 [M]; T = new INT32 [M]; D = new INT32 [M]; Lzero(S); Lzero(T); Lzero(D); if(Lget_last(X) <= LP_preci + 2 && X[m] < _I9000) { S[m+1] = 1, S[m] = _I1000, k = 0; while(Lnonzero_first(X) < m + 1) { ++k; Lproduct(X, S, X); } Lquotient(X, S, X); if(--k > 0) { if(k <= _I9999) T[m+1] = k; else if(k <= _I99999999) T[m+2] = (INT32)(k / _I10000), T[m+1] = (INT32)(k - T[m+2] * _I10000); Lln(S, D);//=ln(1.1) Lproduct(T, D, D);//=T*ln(1.1) } S[m] = 0; } S[m+1] = 1, k = 0; Lminus(X, S, X); while(1) { if((k *= -1) >= 0) ++k; else --k; Lproduct(X, S, S); Ldiv_long(S, k, T); Lplus(T, Ans, Ans); if(Lnonzero_first(T) <= 0) break;//值已最小或 0 } delete [] S; delete [] T; Lminus(Ans, D, Ans); Lminus(Ans, P, Ans); delete [] D; delete [] P; } LP_preci = Save_LP_preci; delete [] X; return 0; } bool Lln_ten(INT32 *t)//20031112 - 自然對數 : 真數 = 10 (新版) { if(oTEN[m+1] == 2 && Lget_last(oTEN) <= LP_preci) { Lcopy(oTEN, t); return 0; } Lzero(t); t[m+1] = 10; Lln(t, t); Lcopy(t, oTEN); return 0; } void Lright_move(INT32 *Ob, INT32 *Ans)//使 Ob 每一位數向右位移一位 { INT64 i; Ans[n] = Ob[n], Ans[0] = Ob[0] / 10; for(i = 0; i < M - 3; ++i) { if(Ob[i+1] == 0) { Ans[i+1] = 0; continue; } Ans[i] += (Ob[i+1] % 10) * _I1000, Ans[i+1] = Ob[i+1] / 10; } } void Lleft_move(INT32 *Ob, INT32 *Ans)//使 Ob 每一位數向左位移一位 { INT64 i, k, tmp; Ans[n] = Ob[n], tmp = Ob[M-2] * 10; if(tmp > _I9999) { k = tmp / _I10000, Ans[M-2] = tmp - k * _I10000; } else Ans[M-2] = tmp; for(i = M - 2; i > 0; --i) { if(Ob[i-1] == 0) { Ans[i-1] = 0; continue; } Ans[i-1] = Ob[i-1], tmp = Ob[i-1] * 10; if(tmp > _I9999) { k = tmp / _I10000, Ans[i] += k, Ans[i-1] = tmp - k * _I10000; } else Ans[i-1] = tmp; } } INT64 LRightFirstNonZeroFromAssignPos(const INT32 *A, INT64 Pos)//由指定點往右找出第一個不為零之 INT32 元素 { INT64 i; if(Pos >= n) Pos = n - 1; else if(Pos < 0) Pos = 0; for(i = Pos; i >= 0; --i) if(A[i] != 0) return i; return -1;//全部 0 } INT64 LLeftFirstNonZeroFromAssignPos(const INT32 *A, INT64 Pos)//由指定點往左找出第一個不為零之 INT32 元素 { INT64 i; if(Pos >= n) Pos = n - 1; else if(Pos < 0) Pos = 0; for(i = Pos; i < n; ++i) if(A[i] != 0) return i; return -1;//全部 0 } INT64 Lnonzero_first(const INT32 *A)//找出第一個不為零之 INT32 元素 { INT64 i; for(i = M - 2; i >= 0; --i) if(A[i] != 0) return i; return -1;//全部 0 } INT32 Lone_minus(INT32 *A)//計數器, 整數陣列變數 A[] 自身減 1 { INT64 i; i = Lnonzero_first(A); if(i == -1 && (A[n] == 0 || A[n] == -3))//值為 0 { A[n] = -1; } else if(i <= m && (A[n] == 0 || A[n] == -3))//處理小於 1 之正非整數 { INT32 *one; one = new INT32 [M]; Lzero(one); one[m+1] = 1; i = Lminus(A, one, A); delete [] one; return i; } if(A[n] == -1 || A[n] == -4) { A[n] = 0; i = Lone_plus(A); A[n] = -1; return i; } A[m+1] -= 1; for(i = m+1; i < n; ++i) { if(A[i] < 0) { A[i] += _I10000; A[i+1] -= 1; } else if(i < M - 2 && A[i+1] >= 0) break; } return 0; } INT32 Lone_plus(INT32 *A)//整數陣列變數 A[] 自身加 1 { INT64 i; i = Lnonzero_first(A); if(i == -1 && (A[n] == -1 || A[n] == -4))//值為 0 { A[n] = 0; } else if(i <= m && (A[n] == -1 || A[n] == -4))//處理小於 1 之負非整數 { INT32 *one; one = new INT32 [M]; Lzero(one); one[m+1] = 1; i = Lplus(A,one,A); delete [] one; return i; } if(A[n] == -1 || A[n] == -4) { A[n] = 0; i = Lone_minus(A); A[n] = -1; if(Lnonzero_first(A) == -1)//值為 0 { A[n] = 0; } return i; } A[m+1] += 1; for(i = m + 1; i < n; ++i) { if(A[i] > _I9999) { A[i] -= _I10000; A[i+1] += 1; } else if(i < M - 2 && A[i+1] < _I10000) break; } return 0; } INT32 Lone_np_quotient(INT64 N, INT32 *Ans)//求出 1/(n!) { INT64 i, Save_LP_preci = LP_preci; if(N < 0) { //LP_preci = Save_LP_preci; return (Ans[n] = 5);//錯誤輸入負數值 } for(i = 0; i < M; ++i) Ans[i] = 0; Ans[m+1] = 1; if(N == 0)//除數為0 { //LP_preci = Save_LP_preci; return 0; } LP_preci = 1; while(1) { Ldiv_long(Ans, N, Ans); if(N == 1) break; else if(Lnonzero_first(Ans) <= 0)//值已最小或 0 { LP_preci = Save_LP_preci; return (Ans[n] = 7); } --N; } LP_preci = Save_LP_preci; for(i = Save_LP_preci - 3; i >= 0; --i) Ans[i] = 0; return 0; } void Lcopy(const INT32 *becopy, INT32 *copy)//複製 INT32 陣列 { for(INT64 i = 0; i < M; ++i) copy[i] = becopy[i]; } void LcopyAssign(const INT32 *becopy, INT32 *copy, const INT64 first, const INT64 end)//複製指定 INT32 元素:0 ~ M-1 { INT64 i = first; if(i < 0) i = 0; for(; i <= end && i < M; ++i) copy[i] = becopy[i]; } INT32 Lnp(INT32 *N, INT32 *Ans)//N 階乘 N! { INT64 i, Save_LP_preci = LP_preci; INT32 *np; np = new INT32 [M]; if(Lnonzero_first(N) == -1 && N[n] <= 0) { Lzero(Ans), Ans[m+1] = 1;//0 階乘 LP_preci = Save_LP_preci; delete [] np; return 0; } if((Lget_last(N) < m) || N[n] == -1 || N[n] == -4 || N[n] > 0 || N[m] != 0) { LP_preci=Save_LP_preci; delete [] np; return (Ans[n] = 5);//錯誤輸入非整數或負數值 } for(i = 0; i < M; ++i) Ans[i] = np[i] = N[i]; LP_preci = m; while(1) { Lone_minus(np); if((np[m+1] == 0 && Lget_first(np) == m + 1) || Ans[n]!=0) { if(Ans[n] != 0)//Ans[n] == -1)//bug fixed 20040114 { LP_preci = Save_LP_preci; delete [] np; return (Ans[n] = 6);//最高位數溢位 } break; } Lproduct(Ans, np, Ans); } LP_preci = Save_LP_preci; delete [] np; return 0; } INT64 Lget_first(const INT32 *num)//find the first in INT32 [] { INT64 i; for(i = M - 2; i > m; --i) if(num[i] != 0) return i; return m + 1;//個位數 } INT64 Lget_last(const INT32 *num)//find the last in INT32 [] { INT64 i; for(i = 0; i <= m; ++i) if(num[i] != 0) return i; return m;//小數第一位 } void L_IntMatrixToStr(INT32 *S, char *s)//轉換 calcl 整數陣列到 char *s { INT64 i, k, p = 0, stop_i; char sadd[9]={'\0','\0','\0','\0','\0','\0','\0','\0','\0'}; LModLastAns(S);//處理結果進位,用在 L_IntMatrixToStr() 裡 stop_i = Lget_last(S); //////////////////////////////////////////////////////////////////////////// if(S[n] == -1) s[p] = '-', ++p; else if(S[n] == -3) s[p] = '+', s[++p] = '|', s[++p] = '-', ++p; else if(S[n] == -4) s[p] = '-', s[++p] = '|', s[++p] = '+', ++p; else if(S[n] == 0); else if(S[n]> 0) { sprintf(s, "Calcl Error : #%d", S[n]); } for(i = M - 2; i > m; --i) if(S[i] != 0 || i == m + 1) break; for(i = i, k = 1; i >= stop_i; --i) { if(i > m && k == 1) { sprintf(sadd, "%d", S[i]); k = 0; } else { #ifdef _SYS64 sprintf(sadd, "%08d", S[i]); #else sprintf(sadd, "%04d", S[i]); #endif } if(sadd[0] != '\0') { s[p] = sadd[0], ++p, s[p] = '\0'; if(sadd[1] != '\0') { s[p] = sadd[1], ++p, s[p] = '\0'; if(sadd[2] != '\0') { s[p] = sadd[2], ++p, s[p] = '\0'; if(sadd[3] != '\0') { s[p] = sadd[3], ++p, s[p] = '\0'; #ifdef _SYS64 if(sadd[4] != '\0') { s[p] = sadd[4], ++p, s[p] = '\0'; if(sadd[5] != '\0') { s[p] = sadd[5], ++p, s[p] = '\0'; if(sadd[6] != '\0') { s[p] = sadd[6], ++p, s[p] = '\0'; if(sadd[7] != '\0') { s[p] = sadd[7], ++p, s[p] = '\0'; } } } } #endif } } } } if(i - 1 == stop_i && S[i-1] == 0) break; if(i - 1 == m) s[p] = '.', ++p, s[p] = '\0'; } #if (__DEBUG == 1) cout << endl; LCshowf(S); cout << endl; #endif } void LCshowf(INT32 *S)//INT32[] format showing in console : 在 Console 中輸出至螢幕 { INT64 i, k, stop_i = Lget_last(S); if(S[n] == -1) printf("-"); else if(S[n] == -3) printf("+|-"); else if(S[n] == -4) printf("-|+"); else if(S[n] == 0); else if(S[n] > 0) { cout << "Calcl Error : #" << S[n]; return; } for(i = M - 2; i > m; --i) if(S[i] != 0 || i == m + 1) break; for(i = i, k = 1; i >= stop_i; --i) { if(i > m && k == 1) { cout << S[i]; k = 0; } else { #ifdef _SYS64 cout << setw(8) << setfill('0') << S[i]; #else cout << setw(4) << setfill('0') << S[i]; #endif } if(i - 1 == stop_i && S[i-1] == 0) break; if(i-1 == m) cout << '.'; } } void Lzero(INT32 *Z)//make INT32 : [] be 0 { for(INT64 i = 0; i < M; ++i) Z[i] = 0;//起始 0 } INT32 Lmode(char *S, INT32 *Mode)//a string to be a format INT32 [] { INT64 i, i2, k, DEL_p, stop_S; char buffer[9] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; Lzero(Mode); /* test the string *S */ for(k = i = 0; S[i] != '\0'; ++i) { if(S[i] == '.'&& k == 0) { k = 1; } else if(i == 0 && ( (S[0] == '+' && S[1] == '|' && S[2] == '-') || (S[0] == '-' && S[1] == '|' && S[2] == '+') || (S[0] == '+' && S[1] == '|' && S[2] == '+') || (S[0] == '-' && S[1] == '|' && S[2] == '-'))) { i += 3; } else if(((i > 0 || (i == 0 && S[i] != '+' && S[i] != '-')) && S[i] != '.' && (S[i] < '0' || S[i] > '9')) || (S[i] == '.' && k == 1)) { return (Mode[n] = 13);//error : 非數字字元 } } if(S[0] == '-') { /* if(Lnonzero_first(Mode)==-1)//值為 0 { Mode[n]=0;//沒 - 符號的 0 值 } else*///解除上三行的註解符號則 0 值輸出 Mode[n] 將無 - 符號 Mode[n] = -1; } else if(S[0] == '+' && S[1] == '|' && (S[2] == '-' || S[2] == '+')) { Mode[n] = -3; for(i = 1; S[i] != '\0'; ++i) S[i] = S[i+2]; } else if(S[0] == '-' && S[1] == '|' && (S[2] == '+' || S[2] == '-')) { Mode[n] = -4; for(i = 1; S[i] != '\0'; ++i) S[i] = S[i+2]; } else Mode[n] = 0;//+ if(S[0] == '+' || S[0] == '-') i = 1; else i = 0; for(DEL_p = -1, stop_S = -1; S[i] != '\0'; ++i) { if(S[i] == '.' && DEL_p == -1) DEL_p = i; else if(S[i] > '9' || S[i] < '0') { stop_S = i - 1; break; } } if(stop_S == -1) stop_S = i - 1; if(DEL_p == -1)//純整數 { INT64 stop_i; if(S[0] == '+' || S[0] == '-') stop_i = 1; else stop_i = 0; buffer[0] = buffer[1] = buffer[2] = buffer[3] = '0'; #ifdef _SYS64 k = 8; buffer[4] = buffer[5] = buffer[6] = buffer[7] = '0', buffer[8] = '\0'; #else k = 4; buffer[4] = '\0'; #endif for(i2 = m + 1, i = stop_S; i >= stop_i && i2 < n; --i) { --k, buffer[k] = S[i]; if((k == 0 && i2 < n) || i == stop_i) { Mode[i2] = atoi(buffer); buffer[0] = buffer[1] = buffer[2] = buffer[3] = '0'; #ifdef _SYS64 k = 8; buffer[4] = buffer[5] = buffer[6] = buffer[7] = '0', buffer[8] = '\0'; #else k = 4; buffer[4] = '\0'; #endif ++i2; if(i2 == n && i > stop_i) { Lzero(Mode); return (Mode[n] = 6);//溢位 } } } } else//含小數數值 { INT64 stop_i; if(S[0] == '+' || S[0] == '-') stop_i = 1; else stop_i = 0; buffer[0] = buffer[1] = buffer[2] = buffer[3] = '0'; #ifdef _SYS64 k = 8; buffer[4] = buffer[5] = buffer[6] = buffer[7] = '0', buffer[8] = '\0'; #else k = 4; buffer[4] = '\0'; #endif for(i2 = m + 1, i = DEL_p - 1; i >= stop_i && i2 < n; --i) { --k, buffer[k] = S[i]; if((k == 0 && i2 < n) || i == stop_i) { Mode[i2] = atoi(buffer); buffer[0] = buffer[1] = buffer[2] = buffer[3] = '0'; #ifdef _SYS64 k = 8; buffer[4] = buffer[5] = buffer[6] = buffer[7] = '0', buffer[8] = '\0'; #else k = 4; buffer[4] = '\0'; #endif ++i2; if(i2 == n && i > stop_i) { Lzero(Mode); return (Mode[n] = 6);//溢位 } } } buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[4] = buffer[5] = buffer[6] = buffer[7] = buffer[8] = '\0'; for(k = 0, i2 = m, i = DEL_p + 1; i <= stop_S && i2 >= LP_preci - 2 && i2 >= 0; ++i) { buffer[k] = S[i], ++k; #ifdef _SYS64 if((k == 8 && i2 < n) || i + 1 > stop_S) { Mode[i2] = atoi(buffer); if(Mode[i2] < 10) Mode[i2] *= 10000000; else if(Mode[i2] < 100) Mode[i2] *= 1000000; else if(Mode[i2] < 1000) Mode[i2] *= 100000; else if(Mode[i2] < 10000) Mode[i2] *= 10000; else if(Mode[i2] < 100000) Mode[i2] *= 1000; else if(Mode[i2] < 1000000) Mode[i2] *= 100; else if(Mode[i2] < 10000000) Mode[i2] *= 10; if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0' && buffer[3] == '0' && buffer[4] == '0' && buffer[5] == '0' && buffer[6] == '0') Mode[i2] /= 10000000; else if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0' && buffer[3] == '0' && buffer[4] == '0' && buffer[5] == '0') Mode[i2] /= 1000000; else if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0' && buffer[3] == '0' && buffer[4] == '0') Mode[i2] /= 100000; else if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0' && buffer[3] == '0') Mode[i2] /= 10000; else if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0') Mode[i2] /= 1000; else if(buffer[0] == '0' && buffer[1] == '0') Mode[i2] /= 100; else if(buffer[0] == '0') Mode[i2] /= 10; k = 0, buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[4] = buffer[5] = buffer[6] = buffer[7] = buffer[8] = '\0'; --i2; } #else if((k == 4 && i2 < n) || i + 1 > stop_S) { Mode[i2] = atoi(buffer); if(Mode[i2] < 10) Mode[i2] *= 1000; else if(Mode[i2] < 100) Mode[i2] *= 100; else if(Mode[i2] < 1000) Mode[i2] *= 10; if(buffer[0] == '0' && buffer[1] == '0' && buffer[2] == '0') Mode[i2] /= 1000; else if(buffer[0] == '0' && buffer[1] == '0') Mode[i2] /= 100; else if(buffer[0] == '0') Mode[i2] /= 10; k = 0,buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[4] = '\0'; --i2; } #endif } } #if (__DEBUG == 1) cout << endl; LCshowf(Mode); cout << endl; #endif return 0; } INT32 Lplus(const INT32 *A0, const INT32 *B0, INT32 *Ans)//INT32 [] : plus { INT64 i, stop = -1; INT32 *A, *B; A = new INT32 [M]; B = new INT32 [M]; for(i = n; i >= 0; --i) { A[i] = A0[i], B[i] = B0[i], Ans[i] = 0; if(stop == -1 && i < n && (A[i] != 0 || B[i] != 0)) { if(i < M - 2) stop = i + 1; else stop = i; } } if(((A[n] == 0 || A[n] == -3) && (B[n] == -1 || B[n] == -4)) || ((A[n] == -1 || A[n] == -4) && (B[n] == 0 || B[n] == -3))) { if(A[n] == 0 || A[n] == -3) { B[n] = 0; Lminus(A, B, Ans); } else { A[n] = 0; Lminus(B, A, Ans); } delete [] A; delete [] B; return 0; } Ans[n] = A[n];//Here : A[n]==B[n] : the sign of + or - if(LP_preci - 2 >= 0) i = LP_preci - 2; else i = 0; for(; i <= stop; ++i) { if(A[i] == 0 && A[i] == B[i]) continue; Ans[i] += A[i] + B[i]; if(Ans[i] > _I9999) { Ans[i] -= _I10000; if(i + 1 < M) Ans[i+1] += 1; else { delete [] A; delete [] B; return (Ans[n] = 1);//溢位#1 } } } delete [] A; delete [] B; return 0; } INT32 Lminus(const INT32 *A0, const INT32 *B0, INT32 *Ans)//INT32 [] : minus { INT64 i, stop = -1; INT32 *A, *B; A = new INT32 [M]; B = new INT32 [M]; for(i = n; i >= 0; --i) { A[i] = A0[i], B[i] = B0[i], Ans[i] = 0; if(stop == -1 && i < n && (A[i] != 0 || B[i] != 0)) { if(i < M - 2) stop = i + 1; else stop = i; } } if(((A[n] == 0 || A[n] == -3) && (B[n] == -1 || B[n] == -4)) || ((A[n] == -1 || A[n] == -4) && (B[n] == 0 || B[n] == -3))) { if(A[n] == 0 || A[n] == -3) B[n] = 0; else B[n] = -1; Lplus(A, B, Ans); delete [] A; delete [] B; return 0; } else if(A[n] == -1 || A[n] == -4) { B[n] = A[n] = 0; Lminus(B, A, Ans); delete [] A; delete [] B; return 0; } for(i = stop; i >= 0; --i) { if(B[i] > A[i]) { Lminus(B, A, Ans), Ans[n] = -1; delete [] A; delete [] B; return 0; } else if(B[i] != A[i]) break; } Ans[n] = 0; if(LP_preci - 2 >= 0) i = LP_preci - 2; else i = 0; for(; i <= stop; ++i) { if(Ans[i] >= 0 && A[i] == 0 && A[i] == B[i]) continue; Ans[i] += A[i] - B[i]; if(Ans[i] < 0) { Ans[i] += _I10000; if(i < M - 2) Ans[i+1] -= 1; else { delete [] A; delete [] B; return (Ans[n] = 2);//溢位#2 } } } delete [] A; delete [] B; return 0; } INT32 Lproduct(const INT32 *A0, const INT32 *B0, INT32 *Ans) { INT64 i, j, t, I, J, sI, sJ, k, tmpLP; INT64 buffer, buffer2; INT32 *A, *B; A = new INT32 [M]; B = new INT32 [M]; if(LP_preci - 4 >= 0) tmpLP = LP_preci - 4;//!!!!!! else tmpLP = 0; for(A[n] = A0[n], B[n] = B0[n], i = n - 1, sI = sJ = -1; i >= 0; --i) { A[i] = A0[i], B[i] = B0[i], Ans[i] = 0; if(sI == -1 && A[i] != 0) sI = i; if(sJ == -1 && B[i] != 0) sJ = i; } for(I = J = -1, i = tmpLP; i <= m; ++i) { if(I == -1 && (A[i] != 0 || i == m)) I = i; if(J == -1 && (B[i] != 0 || i == m)) J = i; if(I != -1 && J != -1) break; } if(((A[n] == 0 || A[n] == -3) && (B[n] == -1 || B[n] == -4)) || ((A[n] == -1 || A[n] == -4) && (B[n] == 0 || B[n] == -3))) Ans[n] = -1;//sign is - else Ans[n] = 0; for(j = J; j <= sJ; ++j) { for(i = I, k = i + j - m - 1; B[j] > 0 && i <= sI && k < n; ++i, ++k) { if(k < tmpLP)// continue;//防止小數點末端溢位 { i += tmpLP - k - 1; k = tmpLP - 1; continue;//防止小數點末端溢位 } if((buffer = (INT64)A[i] * (INT64)B[j]) > _I9999)//進位及強制型別轉換(INT64 <--- int) , 只讀取整數部分 { if(k + 1 < n) { buffer2 = buffer; Ans[k+1] += (INT32)(buffer /= _I10000), Ans[k] += (INT32)(buffer2 - (buffer *= _I10000));//強制型別轉換(INT32 <--- long) } else { delete [] A; delete [] B; return (Ans[n] = 3);//最大位數溢位#3 } } else Ans[k] += (INT32)buffer;//強制型別轉換(INT32 <--- long) for(t = k; t < n; ++t)//initial:k = P+j-J { if(Ans[t] > _I9999) { Ans[t] -= _I10000; if(t + 1 < n) Ans[t+1] += 1; else { delete [] A; delete [] B; return (Ans[n] = 3);//最大位數溢位#3 } } if(t + 1 < M - 2 && Ans[t+1] < _I10000 && Ans[t+2] < _I10000) break; } } } #if (__DEBUG == 1) cout << endl << "Ans = "; LCshowf(Ans); cout << endl; #endif delete [] A; delete [] B; return 0; } void LMinusForQuotient(INT32 *A, INT32 *B, const INT64 &stop)//專供除法函式的減法:必須 A >= B >= 0,最後答案傳回在 A { INT64 i; bool A_next = 0; if(LP_preci - 2 >= 0) i = LP_preci - 2; else i = 0; while(i <= stop) { if(A_next == 1 || A[i] != 0 || B[i] != 0) { A[i] -= (A_next + B[i]); if(A[i] < 0) A[i] += _I10000, A_next = 1; else A_next = 0; } ++i; } } INT32 Lquotient(const INT32 *A0, const INT32 *B0, INT32 *Ans)//20030911 changed { INT64 t, h, k, P, Allcount, tmpLP = LP_preci; INT32 *A, *Ans2, *B, *Ans_t; A = new INT32 [M]; B = new INT32 [M]; Ans2 = new INT32 [M]; Ans_t = new INT32 [M]; bool sgn = 0;//0為結果是正數, 1為結果是負數 //20030901 bug fixed 2 - Lcalc_base.h - Lquotient() 修正負數結果時(+/- 或 -/+)的除法錯誤 if(LP_preci - 2 >= 1) tmpLP -= 2; else tmpLP = 1; for(k = n; k >= 0; --k) { if(k >= tmpLP) A[k] = A0[k], B[k] = B0[k], Ans[k] = 0;//初始化 else A[k] = B[k] = Ans[k] = 0;//初始化 } if(((A[n] == 0 || A[n] == -3) && (B[n] == -1 || B[n] == -4)) || ((A[n] == -1 || A[n] == -4) && (B[n] == 0 || B[n] == -3))) sgn = 1;//預先記錄 Ans 的符號(負) - for(A[n] = B[n] = t = 0, P = -1, k = n; k >= 0; --k) { if(k < n && A[k] > 0 && P == -1)//找出最大位數所在(可以在小數部分) --- 被除數 { if((h = Lnonzero_first(B)) == -1) h = 0; if((P = k - h + m + 1) >= n)//#(h-m-1) == (Lnonzero_first(B)-m-1) --- 調整商值之寫入起始位置 { char B_s[10] = "\0", A_s[10] = "\0"; #ifdef _SYS64 if(k <= m && h <= m) sprintf(A_s, "%08d", A[k]); sprintf(B_s, "%08d", B[h]); //20040123 new - 下面這個 if() 對於除數最高位數溢位處理十分重要!勿任意刪改! if((--P) >= n || (k <= m && h <= m && A_s[0] != '0' && (B_s[0] != '0' || B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[1] != '0' && (B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[2] != '0' && (B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[3] != '0' && (B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[4] != '0' && (B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[5] != '0' && (B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[6] != '0' && (B_s[6] != '0' || B_s[7] != '0')) || (k <= m && h <= m && A_s[7] != '0' && B_s[7] != '0') || (k == n - 1 && A[k] > 9999999 && h <= m && (B_s[0] != '0' || B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 999999 && h <= m && (B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 99999 && h <= m && (B_s[2] != '0' || B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 9999 && h <= m && (B_s[3] != '0' || B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 999 && h <= m && (B_s[4] != '0' || B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 99 && h <= m && (B_s[5] != '0' || B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 9 && h <= m && (B_s[6] != '0' || B_s[7] != '0')) || (k == n - 1 && A[k] > 0 && h <= m && B_s[7] != '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 0 && B_s[7] != '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 9 && B_s[6] != '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 99 && B_s[5] != '0' && B_s[6] == '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 999 && B_s[4] != '0' && B_s[5] == '0' && B_s[6] == '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 9999 && B_s[3] != '0' && B_s[4] != '0' && B_s[5] == '0' && B_s[6] == '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 99999 && B_s[2] != '0' && B_s[3] != '0' && B_s[4] != '0' && B_s[5] == '0' && B_s[6] == '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 999999 && B_s[1] != '0' && B_s[2] != '0' && B_s[3] != '0' && B_s[4] != '0' && B_s[5] == '0' && B_s[6] == '0' && B_s[7] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 9999999 && B_s[0] != '0' && B_s[1] != '0' && B_s[2] != '0' && B_s[3] != '0' && B_s[4] != '0' && B_s[5] == '0' && B_s[6] == '0' && B_s[7] == '0')) #else if(k <= m && h <= m) sprintf(A_s, "%04d", A[k]); sprintf(B_s, "%04d", B[h]); //20030902 new - 下面這個 if() 對於除數最高位數溢位處理十分重要!勿任意刪改! if((--P) >= n || (k <= m && h <= m && A_s[0] != '0' && (B_s[0] != '0' || B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0')) || (k <= m && h <= m && A_s[1] != '0' && (B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0')) || (k <= m && h <= m && A_s[2] != '0' && (B_s[2] != '0' || B_s[3] != '0')) || (k <= m && h <= m && A_s[3] != '0' && B_s[3] != '0') || (k == n - 1 && A[k] > 999 && h <= m && (B_s[0] != '0' || B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0')) || (k == n - 1 && A[k] > 99 && h <= m && (B_s[1] != '0' || B_s[2] != '0' || B_s[3] != '0')) || (k == n - 1 && A[k] > 9 && h <= m && (B_s[2] != '0' || B_s[3] != '0')) || (k == n - 1 && A[k] > 0 && h <= m && B_s[3] != '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 0 && B_s[3] != '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 9 && B_s[2] != '0' && B_s[3] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 99 && B_s[1] != '0' && B_s[2] == '0' && B_s[3] == '0') || (h <= 2 * m - n + 2 && k >= m + 1 && A[k] > 999 && B_s[0] != '0' && B_s[1] == '0' && B_s[2] == '0' && B_s[3] == '0')) #endif { delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return (Ans[n] = 3);//最大位數溢位 } } else if(k == n - 1 && h > m)//處理特別溢位!!!!!!!!! { for(t = 0; t < n; ++t) A[t] = A[t+1], B[t] = B[t+1];//全右移 --k, --h; } if(h > 0 || B[h] > 0) break; else { delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return (Ans[n] = 4);//除數為零 } } if(t==0) { if(k < n && B[k] > 0) t = 1; else if(k == 0) { delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return (Ans[n] = 4);//除數為零 } } else if(t != 0 && P != -1) break; } if(P == -1) { delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return 0;//被除數為零 } //////////////////////////////////////////////////////////////////////////// //開始以除法規則運算 Ans[P] = _I9000, Lproduct(Ans, B, Ans_t), Ans[P] = 0;//相乘後可能會跨至前一元素 ( 長達八位數,即二個 INT32 元素 : [P+1] 與 [P] ) Lcopy(Ans_t, Ans2); Ldiv_long(Ans_t, 9, B); if(sgn == 1) Ans[n] = -1;//將負號寫入答案 Ans[n] INT64 k2 = Lnonzero_first(Ans_t), ct = _I10000; if(k2 == -1) k2 = 0; Allcount = _I9000, h = tmpLP - 1, t = 0; while(P >= tmpLP) { for(ct /= 10, k = k2; Allcount > 0; Allcount -= ct, ++k, LMinusForQuotient(Ans2, B, k2)) { for(; k >= h && A[k] >= Ans2[k]; --k) { if(A[k] > Ans2[k] || k == h) { Ans[P] += Allcount;//記入結果:正確之商值 if(k == h) { delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return 0;//結束 } LMinusForQuotient(A, Ans2, k2);// 被除數減去商和除數相乘之積 Allcount = 0;//離開外圍迴圈 break; } } } if((++t) == 1) k = 10; else if(t == 2) k = 100; else if(t == 3) k = 1000; #ifdef _SYS64 else if(t == 4) k = 10000; else if(t == 5) k = 100000; else if(t == 6) k = 1000000; else if(t == 7) k = 10000000; #endif else k = 1, t = 0, ct = _I10000, --P; Allcount = _I9000 / k; for(Ans2[0] = 0, B[0] /= 10, Ans_t[0] /= 10, k = 0; k <= k2; ++k)//測試 INT32 陣列裡之單一元素:千、百、十、個 ----> 我採右移法 { if(B[k+1] == 0 && Ans_t[k+1] == 0) { Ans2[k+1] = 0; continue; } B[k] += (B[k+1]%10)*_I1000, B[k+1] /= 10, Ans2[k] = (Ans_t[k] += (Ans_t[k+1]%10)*_I1000), Ans2[k+1] = (Ans_t[k+1] /= 10); } for(k = k2 + 1; k >= 0; --k) if(A[k] > 0 || Ans_t[k] > 0) {k2 = k; break;};//20030914 修正 bug:k2 錯誤 } delete [] A; delete [] B; delete [] Ans2; delete [] Ans_t; return 0; } #endif
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
- [转帖][Cado-nfs-discuss] 795-bit factoring and discrete logarithms (RSA-240 于2019年12月2日被破解) 19498
- [转帖]How to factor 2048 bit RSA integers in 8 hours using 20 million noisy qubits 8163
- [推荐]RSA-220 has 220 decimal digits (729 bits), and was factored 6895
- [推荐]RSA-210 has been factored. 11179
- Lessons Learned From Previous SSL/TLS Attacks - A Brief Chronology Of Attacks... 8923
看原图
赞赏
雪币:
留言: