我正在尝试为指数移动平均算法构建一个 PHP 扩展。 我是 C 的新手,我相信我有一些转换问题(请参阅下面代码中的注释行)。
预期结果:622.81176945058
实际结果:7.9131985629043E-316
代码:
double computeLastEMA(HashTable *arr_hash, double period)
{
zval **data;
HashPosition pointer;
double k, n;
int i = 0;
k = 2.0 / ((double) period + 1.0 );
// Compute Simple Moving Average
for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS && i < period;
zend_hash_move_forward_ex(arr_hash, &pointer), ++i
) {
n += *(double *) data;
}
n = n / period;
// Compute Exponential Moving Average
for(;
zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS;
zend_hash_move_forward_ex(arr_hash, &pointer)
) {
n += k * ( *(double *) data - n );
i = *(double *) data; // !this is the casting issue!
}
return i;
}
PHP_FUNCTION(lastEMA)
{
zval *values;
HashTable *arr_hash;
long period;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &values, &period) == FAILURE)
{
RETURN_NULL();
}
arr_hash = Z_ARRVAL_P(values);
RETURN_DOUBLE(computeLastEMA(arr_hash, period));
}
我做错了什么?谢谢! (事实上我不知道'*'到底是什么意思!:( )
最佳答案
假设数组中的每个元素都是 double 值,您需要使用 Z_DVAL_PP(data)
将 zval **
转换为 double
值.
for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS && i < period;
zend_hash_move_forward_ex(arr_hash, &pointer), ++i
) {
double value = Z_DVAL_PP(data);
n += value;
}
另一个循环可以用同样的方法修复。
最后,可以在zpp中使用H
类型来简化代码:
HashTable *arr_hash;
double period = 0.f;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|d", & arr_hash, &period) == FAILURE)
{
RETURN_NULL();
}
我还修复了可选的 period
参数中的潜在类型问题。
关于php - C PHP 扩展中的转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24717019/