在不截断或精度损失的情况下删除 ascii 浮点数中的小数点

remove decimal point in ascii float number without truncating or precision loss

我有一个代表电压的ascii浮点数,例如。 5.625V,我需要去掉小数点。我不想截断数字或降低精度我只需要没有小数点的数字。

结果数字将被插入到 ascii 协议中,其字段宽度为 5 位长度,表示电压,单位为 mV(毫伏)与 V(伏特),如上例所示。数字需要显示为5位ascii数字,无十进制。

例如。 5.625V ascii 浮点数到 5625 mV ascii 十进制数..

看起来很简单...但无法找到一种优雅的方式来做到这一点。

只转换毫伏数,不带小数部分:

char buffer[32];
float voltage = 5.625;

snprintf(buffer, sizeof buffer, "%.0f", voltage * 1000.);

如果您想用空格填充 5 个字符,并且您知道 int 中的毫伏数,您可以使用:

snprintf(buffer, sizeof buffer, "%5d", (int)(voltage * 1000));

如果您要用前导零填充 5 个字符,请使用:

snprintf(buffer, sizeof buffer, "%05d", (int)(voltage * 1000));

如果您平台上的 int 只有 16 位,您应该使用更大的类型以避免在转换超过 INT_MAXfloat 时出现未定义的行为。 long long 保证至少为 64 位。相应地调整 printf 格式说明符。

请注意,如果值超出 int 的范围,则转换为 int 会向 0 舍入并调用未定义的行为。如果您知道您的值为正且在范围内,则可以使用 (int)(value * 1000 + 0.5)

获得更高的准确性

问题提示输入的是 ASCII 字符串,所以我想出了这个:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

long s2mv(const char *s)
{
    long mv;
    char *end;
    int sign;

    while (isspace((unsigned char)*s)) {
        s++;
    }

    sign = (*s == '-') ? -1 : 1;
    if (*s == '-' || *s == '+') {
        s++;
    }

    mv = 1000 * strtol(s, &end, 10);
    s = end;
    if (*s++ == '.') {
        int place = 100;

        while (place && isdigit((unsigned char)*s)) {
            mv += place * (*s - '0');
            s++;
            place /= 10;
        }
    }
    return mv * sign;
}

int main(void)
{
    const char *tests[] = {
        "0", "12", "-12", "12.", "-12.", "12.345", "-12.345",
        "1.234", ".123", "0.123", "-0.123", "-.123"
    };
    long mv;
    int i;

    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
        mv = s2mv(tests[i]);
        printf("s2mv(\"%s\") returned %ld\n", tests[i], mv);
    }
    return 0;
}

输出:

s2mv("0") returned 0
s2mv("12") returned 12000
s2mv("-12") returned -12000
s2mv("12.") returned 12000
s2mv("-12.") returned -12000
s2mv("12.345") returned 12345
s2mv("-12.345") returned -12345
s2mv("1.234") returned 1234
s2mv(".123") returned 123
s2mv("0.123") returned 123
s2mv("-0.123") returned -123
s2mv("-.123") returned -123