microPython的源码解析之 formatfloat.c

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.

microPython 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
  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值