math - 无递归的浮点幂函数
问题描述
GLSL 没有pow
用于双精度类型的函数。此函数的经典实现使用递归。由于 GLSL 中不允许递归,我需要一个无递归的实现。
我也需要这个exp
功能。
解决方案
这个问题可以简单地通过分成两个子问题来解决。
- 分离指数的整体和小数部分
- 计算整个部分的功率(这是相当微不足道的)
- 用小数部分计算功率(使用近似值)
- 乘以结果
- 如果初始指数为负,则反转结果
/// This is a simple non recursive implementation for pow, where the exponent is an integer.
double pow(double base, int power) {
double res = 1.0;// Initialize result
while (power > 0.0) {
// If power is odd, multiply x with result
if (power % 2 == 1) {
res *= base;
}
// n must be even now
power /= 2;
base *= base;// Change x to x^2
}
return res;
}
// The desired precision. More precision results in slower execution.
const double EPSILON = 0.00000001;
double pow(double base, double power) {
// We want to ignore negative exponents for now. We invert our result at the if necessary.
bool negative = power < 0.0LF;
if (negative) {
power *= -1.0LF;
}
// Seperate the whole and fractional parts.
double fraction = power - int(power);
int integer = int(power - fraction);
// The whole part is easily calculated.
double intPow = pow(base, integer);
// The fractional part uses an approximation method.
double low = 0.0LF;
double high = 1.0LF;
double sqr = sqrt(base);
double acc = sqr;
double mid = high / 2.0LF;
while (abs(mid - fraction) > EPSILON) {
sqr = sqrt(sqr);
if (mid <= fraction) {
low = mid;
acc *= sqr;
} else {
high = mid;
acc *= (1.0LF / sqr);
}
mid = (low + high) / 2.0LF;
}
// Exponential rules allow us to simply multiply our results.
double result = intPow * acc;
// If we started with a negative exponent we invert the result.
if (negative) {
return 1.0LF / result;
}
return result;
}
const double E = 2.7182818284590452353602874LF;
/// e^x is as simple as that.
double exp(double power) { return pow(E, power); }
表现
的平均迭代次数exp(random(0.0, 100.0))
:
EPSILON = 0.0001 -> 16.0763
EPSILON = 0.00001 -> 19.4108
EPSILON = 0.000001 -> 22.6639
EPSILON = 0.0000001 -> 26.0477
EPSILON = 0.00000001 -> 29.3929
推荐阅读
- node.js - 如何在节点应用程序中持久化 EventEmitter 对象?
- r - 尝试在数据框中用零替换一组数字
- tsql - 如何杀死 MS SQL 2016 tcp 监听器
- c# - 在客户端(App 端)接收 Multipart/form-data 响应
- java - 使用hibernate将数据从文件上传到mysql时减少时间
- c# - 如何删除 WPF 中的组合框?
- zabbix - 如何将日语添加到 Zabbix 前端?
- python-2.7 - 解析错误:符号处的 WHERE 标识符无效 (
- plugins - UE4 - 包括实验性引擎插件
- sql - oracle sql中选择具有不同值的列的方法