嵌入式开发中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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值