math_modf是lua库函数math.modf的具体实现,和math_ceil、math_floor不同,math_modf不使用任何的C标准库函数,独立地实现了和C标准库函数modf相同的功能。math_modf的声明如下:
static int math_modf (lua_State *L);
math_modf的目的是获得一个浮点数的整数部分(向0取整)和小数部分。
math_modf的实现:
/*
** next function does not use 'modf', avoiding problems with 'double*'
** (which is not compatible with 'float*') when lua_Number is not
** 'double'.
*/
static int math_modf (lua_State *L) {
if (lua_isinteger(L ,1)) {
lua_settop(L, 1); /* number is its own integer part */
lua_pushnumber(L, 0); /* no fractional part */
}
else {
lua_Number n = luaL_checknumber(L, 1);
/* integer part (rounds toward zero) */
lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
pushnumint(L, ip);
/* fractional part (test needed for inf/-inf) */
lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
}
return 2;
}
为什么lua不直接使用C标准库的modf函数获取浮点数的整数副本和小数部分呢?先看modf的声明:
double modf (double x, double* intpart);
当LUA_NUMBER不是double类型时(LUA_NUMBER可以宏定义为float类型),double* 和float*并不兼容,这样可能会导致一些问题。 看代码:
if (lua_isinteger(L ,1)) {
lua_settop(L, 1); /* number is its own integer part */
lua_pushnumber(L, 0); /* no fractional part */
}
math_modf先判断参数本身是不是整数;如果是的话,直接将其设置到栈顶作为整数部分,再压入0作为小数部分;否则继续执行:
else {
lua_Number n = luaL_checknumber(L, 1);
/* integer part (rounds toward zero) */
lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
pushnumint(L, ip);
/* fractional part (test needed for inf/-inf) */
lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
}
math_modf取整数部分,采用向0舍入的策略;然后用浮点数减去整数部分得到小数部分。例如: