MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
#include "py/mpconfig.h"
#include "py/misc.h"
#if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE
// 包含处理浮点数所需的头文件
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include "py/formatfloat.h"
/***********************************************************************
将任意浮点数转换为字符串的函数。
此函数中的代码灵感来自于 Fred Bayer 的 pdouble.c。
由于 pdouble.c 是以公共领域发布的,我将此代码也以公共领域发布。
原始代码可以在 https://github.com/dhylands/format-float 找到
戴夫·海兰兹
***********************************************************************/
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
// float类型:1个符号位,8个指数位,23个尾数位。
// 指数值为0和255是保留的,指数可以是1到254。
// 指数存储时带有偏移量127。
// 最小和最大的浮点数大约是1x10^37和1x10^-37
#define FPTYPE float
#define FPCONST(x) x##F // 用于创建浮点常量
#define FPROUND_TO_ONE 0.9999995F // 用于四舍五入的常量
#define FPDECEXP 32 // 十进制指数
#define FPMIN_BUF_SIZE 6 // 最小缓冲区大小,用于存储格式化后的浮点数
// 定义FLT_SIGN_MASK用于获取float类型的符号位
#define FLT_SIGN_MASK 0x80000000
// 内联函数用于检查float类型的符号位
static inline int fp_signbit(float x) {
mp_float_union_t fb = {
x};
return fb.i & FLT_SIGN_MASK;
}
#define fp_isnan(x) isnan(x) // 检查浮点数是否是NaN(不是一个数字)
#define fp_isinf(x) isinf(x) // 检查浮点数是否是无穷大
static inline int fp_iszero(float x) {
mp_float_union_t fb = {
x};
return fb.i == 0;
}
static inline int fp_isless1(float x) {
mp_float_union_t fb = {
x};
return fb.i < 0x3f800000;
}
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
// double类型的定义
#define FPTYPE double
#define FPCONST(x) x // 创建双精度浮点常量
#define FPROUND_TO_ONE 0.999999999995 // 用于四舍五入的常量
#define FPDECEXP 256 // 双精度浮点数的十进制指数
#define FPMIN_BUF_SIZE 7 // 最小缓冲区大小,用于存储格式化后的双精度浮点数
#define fp_signbit(x) signbit(x) // 检查双精度浮点数的符号位
#define fp_isnan(x) isnan(x) // 检查双精度浮点数是否是NaN
#define fp_isinf(x) isinf(x) // 检查双精度浮点数是否是无穷大
#define fp_iszero(x) (x == 0) // 检查双精度浮点数是否为零
#define fp_isless1(x) (x < 1.0) // 检查双精度浮点数是否小于1
#endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE
// 内联函数用于获取浮点数的指数值
static inline int fp_expval(FPTYPE x) {
mp_float_union_t fb = {
x};
return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET;
}
// 将浮点数格式化为字符串的函数
int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {
char *s = buf; // 指向缓冲区的指针,用于构建字符串
// 检查缓冲区是否足够大以存储任何浮点数
if (buf_size <= FPMIN_BUF_SIZE) {
// 如果缓冲区不足以存储浮点数(加上空终止符)
// 则不尝试格式化浮点数
if (buf_size >= 2) {
*s++ = '?'; // 如果缓冲区足够大,存储一个问号
}
if (buf_size >= 1) {
*s = '\0'; // 确保字符串以空字符结尾
}
return buf_size >= 2; // 返回是否有足够的空间存储至少一个字符
}
if (fp_signbit(f) && !fp_isnan(f)) {
*s++ = '-'; // 如果浮点数是负数且不是NaN,添加负号
f = -f; // 取反浮点数
} else {
if (sign) {
*s++ = sign; // 如果提供了符号,添加到字符串
}
}
// buf_remaining 表示可用于存储数字和指数的字节数
// 它是 buf_size 减去用于符号和空终止符的空间
int buf_remaining = buf_size - 1 - (s - buf);
{
char uc = fmt & 0x20; // 获取fmt的大小写标志
if (fp_isinf(f)) {
// 如果浮点数是无穷大,添加相应的字符串
*s++ = 'I' ^ uc;
*s++ = 'N' ^ uc;
*s++ = 'F' ^ uc;
goto ret;
} else if (fp_isnan(f)) {
// 如果浮点数是NaN,添加相应的字符串
*s++ = 'N' ^ uc;
*s++ = 'A' ^ uc;
*s