hzx*_*zxu 0 algorithm objective-c nsnumber ios
假如我有一个NSNumber,介于0和1之间,并且可以使用X/Y表示,在这种情况下如何计算X和Y?我不想比较:
if (number.doubleValue == 0.125)
{
X = 1;
Y = 8;
}
Run Code Online (Sandbox Code Playgroud)
所以我得到1/8的0.125
那是相对简单的.例如,0.375相当于0.375/1.
第一步是乘以分子和分母,直到分子是一个整数值(a),给你375/1000.
然后找出最大公约数,并将分子和分母除以.
GCD的(递归)函数是:
int gcd (int a, int b) {
return (b == 0) ? a : gcd (b, a%b);
}
Run Code Online (Sandbox Code Playgroud)
如果你用375和调用它1000,它会吐出来,125这样,当你用它除分子和分母时,你就得到了3/8.
(a)正如评论中指出的那样,数字的精度位数可能比整数类型更高(例如IEEE754加倍,32位整数).您可以通过选择具有更大范围的整数(long,或像MPIR这样的bignum库)或选择"足够接近"策略来解决此问题(当小数部分与积分部分相比相对无关紧要时,将其视为整数).
另一个问题是IEEE754中甚至不存在某些数字,例如臭名昭着的0.1和0.3.
除非数字可以表示为受可用精度(例如存在)限制的值的总和,否则您可以期望的最佳值是近似值.2-nn0.3751/4 + 1/8
例如,考虑单精度(你会看到下面的原因,我懒得做整个64位)1/3.作为单个精度值,它存储为:
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
0 01111101 01010101010101010101010
Run Code Online (Sandbox Code Playgroud)
在这个例子中,符号0因此是正数.
指数位给出125,当你减去127偏差时,给出-2.因此,乘数将是,或.2-20.25
尾数位有点棘手.它们形成一个显式的总和1以及位的所有值,其中是1到23(从左到右.所以尾数计算如下:2-n1n
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
0 01111101 01010101010101010101010
| | | | | | | | | | |
| | | | | | | | | | +-- 0.0000002384185791015625
| | | | | | | | | +---- 0.00000095367431640625
| | | | | | | | +------ 0.000003814697265625
| | | | | | | +-------- 0.0000152587890625
| | | | | | +---------- 0.00006103515625
| | | | | +------------ 0.000244140625
| | | | +-------------- 0.0009765625
| | | +---------------- 0.00390625
| | +------------------ 0.015625
| +-------------------- 0.0625
+---------------------- 0.25
Implicit 1
========================
1.3333332538604736328125
Run Code Online (Sandbox Code Playgroud)
当你乘以0.25(见前面的指数),你会得到:
0.333333313465118408203125
Run Code Online (Sandbox Code Playgroud)
现在这就是为什么他们说你只得到大约7位精度的十进制数字(15为IEEE754双精度).
如果你通过我上面的算法传递实际数字,你就不会得到1/3,你会得到:
5,592,405
---------- (or 0.333333313465118408203125)
16,777,216
Run Code Online (Sandbox Code Playgroud)
但这不是算法本身的问题,更多是您可以表示的数字的限制.
请向Wolfram Alpha帮忙进行计算.如果您需要进行任何强调计算器的数学计算,那么这是该工作的最佳工具之一.
顺便说一句,毫无疑问你会注意到尾数位遵循某种模式:
0101010101....这是因为1/3是无限重复的二进制值以及无限重复的十进制值.您需要01在末尾使用无限数量的位来准确表示1/3.