在C语言中创建自己的函数将字符串编码数字转换为 float

标签 c string floating-point

我正在尝试做一个简单的函数,将以字符串形式编码的数字转换为 float ,使用下面的函数(也已附加),使用函数 strtof.

我得到了错误的值,有人可以解决这个问题吗?为什么这会给我不正确的值?

例如,如果输入字符串是 "123456789.123",该函数将返回浮点值 123456789.123...

我正在使用 DevC++

if string == "12345678"
output = 12345678.000000 (CORRECT)

if string == "-12345678"
output = -12345678.000000 (CORRECT)

if string == "123456789"
output = 123456792.000000 (INCORRECT)

if string == "-123456789"
output = -123456792.000000 (INCORRECT)

if string == "1000.1"
output = 999.799988 (INCORRECT)

if string == "-1000.1"
-output = -999.799988 (INCORRECT)

到目前为止我的代码是:

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>


float StringToFloat (uint8_t *var);


int main()
{
    uint8_t string[64] = "-1000.1";

    float value = StringToFloat (string);

    printf("%f", value);

    return 0;
}



float StringToFloat (uint8_t *var)
{
    float multiplier;
    float result = 0;
    bool negative_num = false;
    bool found_comma_or_dot = false;
    uint16_t numbers_before_dot = 0;
    uint16_t numbers_after_dot = 0;
    uint16_t i = 0;

    while (*(var+i) != 0) 
    {
        if (*(var+i) == '-') { negative_num = true; }
        else if (*(var+i) == '.' || *(var+i) == ',') { found_comma_or_dot = true; }
        else 
        {
            if (found_comma_or_dot == false) { numbers_before_dot++; }
            if (found_comma_or_dot == true)  { numbers_after_dot++; }   
        }

        i++;
    }

    multiplier = pow (10, numbers_before_dot-1);


    while (*var != 0) 
    {
        if (*var == '-') { var++; }

        if (numbers_before_dot > 0) 
        {
            numbers_before_dot--;
            result += ( (*var) - 0x30) * (multiplier);
            multiplier /= 10;
        }


        else if (numbers_after_dot > 0) 
        {
            numbers_after_dot--;    
            result += ( (*var) - 0x30) * (multiplier);
            multiplier /= 10;
        }

        var++;
    }

    if (negative_num == true) 
    {
        result *= (-1);
    }

    return result;
}

最佳答案

一个问题是精度。 float 不是很精确。为了通过您的测试用例,将 float 更改为 double。如果您运行此代码,可以看到这一点:

float t = 123456789;
printf("%f\n", t);

您的代码过于复杂。这是一个更巧妙的解决方案。

double StringToFloat(uint8_t *var)
{
        // First check if negative. If it is, just step one step forward
        // and treat the rest as a positive number. But remember the sign.
        double sign = 1; 
        if(*var=='-') {
                sign = -1;
                var++;
        }

        // Read until either the string terminates or we hit a dot
        uint32_t integer_part = 0;
        while(*var != 0) {
                if(*var == '.' || *var == ',') {
                        var++;
                        break;
                }

                integer_part = 10*integer_part + (*var - '0');
                var++;
        }

        // If we hit the string terminator in previous loop, we will do so
        // in the beginning of this loop too. If you think it makes things
        // clearer, you can add the boolean found_comma_or_dot to explicitly
        // skip this loop.
        uint32_t decimal_part = 0;
        uint32_t decimal_size = 0;
        while(*var != 0) {
                decimal_part = 10*decimal_part + (*var - '0');
                var++;
                decimal_size++;
        }

        return sign * (integer_part + decimal_part/pow(10, decimal_size));
}

请注意,我将 uint16_t 更改为 uint32_t 因为我以另一种方式使用它们。如果这对您来说不可行,您可以将它们更改为 float 类型,但这可能会导致精度损失。

使用 uint16_tfloat 是有原因的,但您将不得不忍受这些限制。就是这样。

关于在C语言中创建自己的函数将字符串编码数字转换为 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58655490/

相关文章:

c - 用于 lzw 压缩的可变长度字符串数组

javascript - 使用部分替换存储为字符串的html元素

c++ - 带有 float 的奇怪的谷歌测试失败

c - IEEE 754 和浮点精度

android - DecimalFormat float 上的 NumberFormatException

c - 什么是特权指令?

c - 从 C 指针数组获取我的值

php - 将 lang 函数放入 php 字符串中

c - 为什么我的第二个 printf 没有按预期调用?

c - 调用 fork() 后函数返回值的可见性