嵌入式开发中C语言的浮点数处理问题(2)

  1. Casting with (int):

    • When you cast a double or float to int directly using (int), it truncates the fractional part, essentially performing a floor operation if the number is positive, but a ceiling operation if the number is negative.
    • For example:
      double x = 3.7;
      int y = (int)x; // y will be 3
      
      x = -3.7;
      y = (int)x; // y will be -3
      
  2. Using floor:

    • The floor function returns the largest integer value less than or equal to the given number. It always rounds down towards negative infinity.
    • For example:
      double x = 3.7;
      double y = floor(x); // y will be 3.0
      
      x = -3.7;
      y = floor(x); // y will be -4.0
      
  3. Combining (int) with floor:

    • When you combine (int) with floor, you first round down the number to the largest integer less than or equal to the given number, then cast it to an integer. This ensures the same rounding behavior regardless of whether the number is positive or negative.
    • For example:
      double x = 3.7;
      int y = (int)floor(x); // y will be 3
      
      x = -3.7;
      y = (int)floor(x); // y will be -4
      

In the context of the find_deviation_parameters function, using (int)floor(potential_M + 0.5) ensures that potential_M is rounded to the nearest integer before casting it to an int. This is because adding 0.5 to a number and then applying floor effectively rounds the number to the nearest integer.

Here is the refined code snippet ensuring that DEVIATION_M is rounded to the nearest integer:

 

#include <stdio.h>
#include <math.h>
#include <float.h>  // For DBL_MAX

#define FXOSC 27000000.0  // 27 MHz

int find_deviation_parameters(double f_dev, int *DEVIATION_M, int *DEVIATION_E) {
    // Calculate the constant K
    double K = (f_dev * pow(2.0, 17)) / FXOSC;
    
    // Initialize variables to find the closest match
    double closest_f_dev_diff = DBL_MAX;
    int best_DEVIATION_M = -1, best_DEVIATION_E = -1;

    // Iterate over possible values of DEVIATION_E
    for (int DEVIATION_E_local = 0; DEVIATION_E_local < 8; DEVIATION_E_local++) {
        // Calculate the potential DEVIATION_M value
        double potential_M = K / pow(2.0, DEVIATION_E_local) - 8.0;
        
        // Check if potential_M is within the valid range (0 to 7)
        if (potential_M >= 0 && potential_M < 8) {
            // Calculate the actual deviation frequency for this pair
            double actual_f_dev = (FXOSC / pow(2.0, 17)) * (8 + (int)floor(potential_M + 0.5)) * pow(2.0, DEVIATION_E_local);
            double f_dev_diff = fabs(f_dev - actual_f_dev);
            
            // Check if this is the closest match so far
            if (f_dev_diff < closest_f_dev_diff) {
                closest_f_dev_diff = f_dev_diff;
                best_DEVIATION_M = (int)floor(potential_M + 0.5);
                best_DEVIATION_E = DEVIATION_E_local;
            }

            // If potential_M is an integer within the valid range (0 to 7), we have an exact match
            if (fabs(potential_M - floor(potential_M + 0.5)) < DBL_EPSILON) {
                *DEVIATION_M = (int)floor(potential_M + 0.5);
                *DEVIATION_E = DEVIATION_E_local;
                return 1;  // Success with an exact match
            }
        }
    }

    // Return the closest match found
    *DEVIATION_M = best_DEVIATION_M;
    *DEVIATION_E = best_DEVIATION_E;
    return 1;  // Success with the closest match
}

int main() {
    double f_dev = 4943.848;  // Example frequency deviation
    int DEVIATION_M, DEVIATION_E;

    if (find_deviation_parameters(f_dev, &DEVIATION_M, &DEVIATION_E)) {
        printf("DEVIATION_M: %d, DEVIATION_E: %d\n", DEVIATION_M, DEVIATION_E);
    } else {
        printf("No valid DEVIATION_M and DEVIATION_E found.\n");
    }

    // Test with a slightly different frequency deviation
    f_dev = 4943.84;
    if (find_deviation_parameters(f_dev, &DEVIATION_M, &DEVIATION_E)) {
        printf("DEVIATION_M: %d, DEVIATION_E: %d\n", DEVIATION_M, DEVIATION_E);
    } else {
        printf("No valid DEVIATION_M and DEVIATION_E found.\n");
    }

    return 0;
}

Summary:

  1. Direct Casting (int) truncates the decimal part and may not work correctly for negative numbers.
  2. floor always rounds down to the nearest integer.
  3. Combining (int) with floor ensures rounding to the nearest integer when adding 0.5, which ensures consistency and correctness in both positive and negative ranges.

This updated function should provide more consistent results for different f_dev values.

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sscanf函数是C语言一个非常常用的函数,它可以将一个字符串按照指定的格式转换成相应的数据类型。在嵌入式开发,sscanf函数也是非常常见的,因为很多时候需要从串口或者其他外部设备读取数据,并将其转换成相应的数据类型进行处理。下面是一些sscanf函数的使用技巧: 1. 使用sscanf函数时一定要注意格式字符串的正确性。格式字符串的占位符必须与待转换的数据类型相对应,否则会发生未知错误。 2. 如果待转换的字符串包含多个数据,可以使用多个占位符进行转换。例如,如果待转换的字符串为"1,2,3",可以使用" %d,%d,%d"的格式字符串进行转换。 3. 可以使用sscanf函数的返回值来判断转换是否成功。如果返回值等于待转换字符串的长度,则说明转换成功,否则转换失败。 4. 如果待转换的字符串包含浮点数,可以使用"%f"或者"%lf"的格式字符串进行转换。 5. 如果待转换的字符串包含十六进制数,可以使用"%x"的格式字符串进行转换。 6. 如果待转换的字符串包含字符或字符串,可以使用"%c"或者"%s"的格式字符串进行转换。 7. 如果待转换的字符串包含指针类型的数据,可以使用"%p"的格式字符串进行转换。 总之,在使用sscanf函数时一定要注意格式字符串的正确性,否则很容易出现转换错误的情况。同时,还应该注意sscanf函数返回值的判断,以确保转换的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值