- 注册时间
- 2016-2-29
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 729
- 在线时间
- 小时
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?欢迎注册
×
大数加,减法目前我所知道的算法:
1)对于用子符串形式表示的数,可以直接相加,减,例:1 的ascii码为49,2 的ascii码为50,1+2的字符串相加为49+50=99 ,再减去一次48等于51,51是3的ascii码。
2)对于直接用数的值表示的数,可以直接相加减,也可以换算成大的进制表示形式进行运算,理论上大进制表示的数运行效率更高,如:1234+4567,当十进制时要运行4次加法,万进制时只需一次加法,那么我们进行大数加法时,有必要把十进制转换成万进制计算完后,再转换回来,答案是没必要,这样做只会更慢,因为进制转换所需时间大大超过十进制的直接加法运算,作为单次的大数加法运算,假如能直接相加(包括用子符串形式表式的数),那么直接相加就是最快的算法。
假如你要进行综合运算,如sin(x)的高精运算,里面有大量的加减乘除运算,一般情况为了更高的计算速度,常常采用大进制表示数,但大进制数加,减计算时会出现指数难以对位的问题。
本篇文章主要也是讨论网上查不到大数加减法中的指数或小数对位问题:
虽然理论上所有的有理数都可以化为整数进行计算,大数库也只提供对整数的支持,但这个例子的整数算法为:1.23E10*1.23E-10;化为整数为(12300000000*123)/10^12 = 1.5129
我的乘法因为直接对有理数操作运算,步骤是这样的,先1.23*1.23= 1.5129;再指数位相加,10+(-10)=0,结果为1.5129E0,这种方法比化为整数再调用整数乘法子程序计算,效率更高,特别是这种(1.23E1000*1.23E-1000)数,更是相差巨大,这些都不是大问题,关键是通过调用大数整数子程序实现的有理数的大数支持,所需的调用前和调用后小数点或指数调整还是很复杂的,最难的是你需要很长的调试验证才能保证运行结果的正确性。
这里我讲讲我的有理数加法(减法原理是一致的)的两种实现:
第一个方法是把数转换为十进制数,再把指数调整为相等,把两数以小数点位置为中心向两边扩充对位,最后运算。
例:1.23456789+9.87654e3 转换为:1.23456789e0+9876.54e0 内存扩充对位为:0001. 23456789+9876. 54000000,然后两数从右向左加,得结果为:9877. 77456789
第二个方法是采用大进制,这里以千进制数讲一下我的具体算法:这里设定千进制下的指数位为十进制下的指数位,十进制数9.87654e3换算成千进制数为009.876 540e3,为什么这么设定,当时也是进行了综合考虑,这样更利于后面的指数对位计算和进制转换。
1.23456789+9.87654e4的千进制表示形式为:0.123 456 789e1+0.987 654e5(这里实际应用时要采用纯小数的表达形式0.xxx...10^n,)
这里也必须要指数对位后才能运算,这里要用到两个参数x=(5-1)\3 =1 ,y=(5-1) mod 3 =1'这里的5是较大的数的指数,1是较小数的指数,3是千进制时的基数,根据x的值把较小的数调整为0.000 123 456 789,再根据y的值把前一次调整后的值调整为0.000 012 345 678 900,此时把两个操作数调整为等长,即:0.000 012 345 678 900+0.987 654 000 000 000,运算,运算后的结果的指数采用较大数的指数,最终结果为9.876663456789e4
其实上述方法中也可以根据x和y的值直接对两数(没有进行后续调整的两数0.123 456 789e1+0.987 654e5)进行运算,代码更简洁,速度有很小的下降,我目前就是采用的这种方法。
为什么我对千进制加法讲了这么多,因为综合运算需要大进制的有理数或无理数加法运算支持,刚开始我不知道大进制下的指数如何对位,我只能把大进制数换算成十进数后再相加,然后在转换回大进制数,大量的进制转换使综合运算效率很低,最后得到一个网友的帮助,对大进制数采用纯小数的表达形式才解决了千进制加法的问题,然后才能使我的落叶高精度表达式计算器1.2版的速度获得了很大的提升。 |
|