控制数值表达式中的取整和小数精度
在涉及乘法或除法的计算中,Analytics 会将结果取整到两个运算数中较大的小数位数。此取整方法与 Analytics 用来评估大多数数值表达式的定点算法相关联。
对于多运算数表达式(如 a*b/c)而言,取整被在该表达式中的每个阶段应用,首先从第一个求值阶段开始,然后一直重复到该表达式被完全求值为止。
说明
未能对 Analytics 中的取整工作原理保持警觉是计算错误的最常见原因之一。
定点算法
Analytics 中的舍入行为与 Analytics 用于数值运算的定点算法相关联(财务函数除外)。Analytics 出于两个原因使用定点算法:
- 可提高处理的速度
- 使用户可以控制小数位和舍入
在乘法中舍入
考虑表达式 1.1 * 1 .1。正确答案是 1.21。但是,Analytics 将该结果取整到一个小数位,因为那是这些运算数中较大的小数位数。
1.1 * 1.1 = 1.2
如果其中一个运算数具有两个小数位,则 Analytics 将该结果的小数部分取整至这些运算数中较大的小数位数。在此特定示例中,不需要取整:
1.10 * 1.1 = 1.21
在除法中舍入
考虑表达式 7/3。正确答案是 2.333... 但是,Analytics 会将该结果取整至零个小数位,因为这两个运算数都没有小数位。
7/3 = 2
如果一个或两个运算数具有小数位,则 Analytics 将该结果的小数部分取整至这些运算数中较大的小数位数:
7/3.00 = 2.33
7.000/3.00 = 2.333
添加小数位以控制舍入
控制取整并获得所需小数精度的最轻松方式是将表达式乘以 1,后面跟您希望在结果中获得的精度的小数位数。例如,乘以 1.0000 可确保结果精确到四个小数位。
示例
问题
在下列表达式中,Analytics 将结果取整至两个小数位,其精度不足以满足您的要求:
7.21 * 2.33 = 16.80
7.21 / 2.33 = 3.09
解决方案
要提高结果的精度,您可以乘以后面跟您所需的精度的小数位数的 1:
1.0000 * 7.21 * 2.33 = 16.7993
1.000000 * 7.21 / 2.33 = 3.094421
注意
将 1 放在表达式的开头。如果您将 1 放到任何其他位置,精度调整可能无法工作,因为要评估的头两个运算数的精度已经导致取整发生:
7.21 * 2.33 * 1.0000 = 16.8000
7.21 / 2.33 * 1.000000 = 3.090000
使用圆括号时要小心
使用圆括号指定数学运算的顺序时要小心。如果您确实使用了圆括号,则精度调整可能无法工作,因为圆括号中的运算数的精度已经导致舍入发生:
1.0000 * (7.21 * 2.33) = 16.8000
将 1 放在圆括号内可解决该问题:
(1.0000 * 7.21 * 2.33) = 16.7993
多运算数表达式中的取整行为
取整行为和小数精度的工作方式相同,而无论表达式包含多少个运算数。Analytics 在以成对方式评估表达式的过程中,将结果取整至两个运算数中较大的小数位数。
但是,由于累积取整在多运算数表达式中的工作格式,要评估的前两个运算数所建立的小数精度是适用于表达式结果的精度。
累积性取整的另一个特点是小数精度的损失会在多运算数表达式的每个阶段增加。
两个小数位精度的示例
下表说明了 Analytics 在计算以下多运算数表达式的过程中如何应用取整:
1.1 * 1.12 * 1.123 * 1.1234 = 1.5514
该表达式的第一个评估阶段中较大的小数位数是 2 ( 1.1 * 1.12 )。此两个小数位精度将贯穿该多运算数表达式的其余部分(由红色数字表示)。
结果差异列显示累积性精度损失如何在求值的每个连续阶段增加。
|
Analytics 计算 (按求值顺序) |
Analytics 结果 (已取整) |
未取整的计算 (按求值顺序) |
未取整的结果 |
结果差异 |
|---|---|---|---|---|
| 1.1 * 1.12 | 1.23 | 1.1 * 1.12 | 1.232 | 0.002 |
| 1.23 * 1.123 | 1.381 | 1.232 * 1.123 | 1.383536 | 0.002536 |
| 1.381 * 1.1234 | 1.5514 | 1.383536 * 1.1234 | 1.5542643424 | 0.0028643424 |
对精度的进一步观察
在 ACL 结果(已取整)列中,与相应的未取整结果相比,前两个小数位之后的所有小数位都是不精确的。在数据分析过程中执行数值计算时,不精确度可能是您的主要忧虑。
在生成它们的具体成对计算的上下文中,取整结果并非不精确的。例如,1.23 * 1.123 = 1.38129 在被按照该规则取整至三个小数位后是 1.381。但是,1.23 是先前从 1.232 取整而来的,这意味着具体的成对计算已包含一定程度的不精确性。
五个小数位精度的示例
下表说明了 Analytics 如何在添加 1.00000 以指定五个小数位的精度之后应用取整:
1.00000 * 1.1 * 1.12 * 1.123 * 1.1234 = 1.55427
该表达式的第一个求值阶段中较大的小数位数是 5 ( 1.00000 * 1.1 )。此五个小数位精度将贯穿该多运算数表达式的其余部分(由红色数字表示)。
|
Analytics 计算 (按求值顺序) |
Analytics 结果 (已取整) |
未取整的计算 (按求值顺序) |
未取整的结果 |
结果差异 |
|---|---|---|---|---|
| 1.00000 * 1.1 | 1.10000 | 1.00000 * 1.1 | 1.10000 | 0.00000 |
| 1.10000 * 1.12 | 1.23200 | 1.10000 * 1.12 | 1.23200 | 0.00000 |
| 1.23200 * 1.123 | 1.38354 | 1.23200 * 1.123 | 1.383536 | 0.000004 |
| 1.38354 * 1.1234 | 1.55427 | 1.383536 * 1.1234 | 1.5542643424 | 0.0000056576 |
指定运算顺序
放置括号可在确定计算中得到的精度级别方面发挥重要作用。使用括号时应十分小心,以免打乱数学运算的正常顺序。
计算每日利息
场景
您需要计算本金 $100,000、年利率 12% 的每日利息。
一个方法
您可以首先计算每日的利率,然后将每日利率乘以 100,000。但是,此方法会产生舍入问题。
100000 * (0.12/365) = 0.00
Analytics 首先将 0.12 除以 365,根据 Analytics 中的舍入规则,这会产生 0.00。实际结果为 0.00032876712...,但是,由于结果被舍入到两个小数位,因此所有后续数字都被丢失。
舍入结果随后被乘以 100000,从而得到 0.00,即使正确答案是 32.876712...
替代方法
您可以首先计算全年利息总金额,然后将该金额除以 365。此替代方法可避免舍入问题。
100000 * 0.12/365 = 32.88
在移除圆括号后,每个计算阶段的结果都保持大于 1,从而避免任何小数取整问题,并且答案被精确到分(两个小数位)。
更改小数精度的工作方式
您可以使用 SET MATH 命令更改小数精度在数值表达式中的工作方式。默认情况下,Analytics 在评估两个运算数时使用较大的或者最大的小数位数。使用最大位数可在表达式的每个阶段保持最大精度。
在命令行或 Analytics 脚本中使用 SET MATH 可更改 Analytics 会话期间的默认行为。在下面的选项一览中,显示了表达式 1.275 * 1.3 的不同结果。实际的未取整结果是 1.6575。
|
命令 |
描述 |
1.275 * 1.3 的结果 |
|---|---|---|
| SET MATH FIRST | 使用运算数对中的第一个运算数的小数位数 | 1.658 |
| SET MATH LAST | 使用运算数对中的最后一个运算数的小数位数 | 1.7 |
| SET MATH MIN | 使用运算数对中的最小小数位数 | 1.7 |
| SET MATH MAX
默认 |
使用运算数对中的最大小数位数 | 1.658 |
| 有关 SET MATH 的详细信息,请参见SET 命令。 | ||