我有一个计算加权产品的程序(我改编自我发现的另一个程序)。但我无法弄清楚如何将total_data
结构的product_state
部分初始化为一个,这样我就不会总是得到零的乘积。现在它保持默认的零值,以便我从SQLite传入的所有值都被清零。
我在大学里学过一些C ++,但从来没有深入到结构中,回到这里就是在我的驾驶室之外。谢谢!
/* product.c */
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1;
#include <stdlib.h>
typedef struct product_state_s {
double total_data; /* sum of (data * weight) values */
double total_wt; /* sum of weight values */
} product_state;
static void product_step( sqlite3_context *ctx, int num_values, sqlite3_value **values )
{
double row_wt = 1.0;
int type;
product_state *st = (product_state*)sqlite3_aggregate_context( ctx,
sizeof( product_state ) );
if ( st == NULL ) {
sqlite3_result_error_nomem( ctx );
return;
}
/* Extract weight, if we have a weight and it looks like a number */
if ( num_values == 2 ) {
type = sqlite3_value_numeric_type( values[1] );
if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
row_wt = sqlite3_value_double( values[1] );
}
}
/* Extract data, if we were given something that looks like a number. */
type = sqlite3_value_numeric_type( values[0] );
if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
st->total_data *= row_wt * sqlite3_value_double( values[0] );
st->total_wt += row_wt;
}
}
static void product_final( sqlite3_context *ctx )
{
double result = 0.0;
product_state *st = (product_state*)sqlite3_aggregate_context( ctx,
sizeof( product_state ) );
if ( st == NULL ) {
sqlite3_result_error_nomem( ctx );
return;
}
if ( st->total_wt != 0.0 ) {
result = st->total_data / st->total_wt;
}
sqlite3_result_double( ctx, result );
}
int product_init( sqlite3 *db, char **error, const sqlite3_api_routines *api )
{
SQLITE_EXTENSION_INIT2(api);
sqlite3_create_function( db, "product", 1, SQLITE_UTF8,
NULL, NULL, product_step, product_final );
sqlite3_create_function( db, "product", 2, SQLITE_UTF8,
NULL, NULL, product_step, product_final );
return SQLITE_OK;
}
答案 0 :(得分:1)
在product_step
中,在您对st == NULL
进行测试后,请尝试添加以下内容:
if (0.0 == st->total_data) st->total_data = 1.0;
通常,您应该非常谨慎地比较浮点值的相等性。浮点数学的精度有限。但是,如果行中没有任何值为零,那么直接比较应该可以正常工作:第一次通过时,sqlite3_aggregate_context
返回的缓冲区已被sqlite归零,因此该值应该等于{{ 1}}。
如果行值为零(并且可能是),则应该向结构添加状态以告知是否已完成初始化:
0.0
以后,而不是测试typedef struct product_state_s {
double total_data; /* sum of (data * weight) values */
double total_wt; /* sum of weight values */
bool did_init;
} product_state;
是否为零,而不是:
st->total_data