我通过UART将两个字符串值接收到stm32f3,并希望将它们连接到一个浮点数,但实际上我看不到如何执行此操作。让我们 在下面的示例中执行此操作。
char *s1="100";
char *s2="09"; //should result in 100.09
float x=???(s1,s2);
我怎样才能做到这一点?
答案 0 :(得分:3)
我将每个字符串转换为整数,然后使用算术:
int whole = atoi(s1);
int frac = atoi(s2);
float x = whole + frac / powf(10, strlen(s2));
最后一部分计算10 ^ strlen(s2),因为" 09"表示09/100," 5"意味着5/10等等。
如果powf()
无法在您的系统上运行(正如您在评论中所述),您可以使用此功能(仅适用于小型非负输入,但这取决于您拥有的功能) :
float myexp10(unsigned x)
{
if (x == 0)
return 1.0;
float res = 10;
while (--x)
res *= 10;
return res;
}
答案 1 :(得分:2)
一种方法是将两个字符串打印到缓冲区中,然后使用strtod
读取float
:
char buf[10];
sprintf(buf, "%.4s.%.4s", s1, s2);
float f = strtod(buf, NULL);
printf("%f\n", f);
请注意,由于100.09
没有float
的精确表示,因此结果将接近100.089996
。
答案 2 :(得分:1)
我会连接两个字符串,中间有一个点,然后使用strtof()来提取浮点数,如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char *s1 = "100";
char *s2 = "09";
char s[strlen(s1) + 1 + strlen(s2) + 1];
strcpy(s, s1);
strcat(s, ".");
strcat(s, s2);
float result = strtof (s, NULL);
printf("%f\n", result);
return 0;
}
输出:
100.089996
如果您的精确度不够,请使用strtod()
,如下所示:
double result = strtod (s, NULL);
答案 3 :(得分:0)
另一种简单但繁琐的方法是将它们存储在char数组中,并使用atof()
进行转换,如下所示:
#include <stdio.h>
#include <string.h> /* strlen */
#include <stdlib.h> /* atof */
float str2float(const char* s1, const char* s2)
{
int size = strlen(s1) + strlen(s2) + 2;
char a[size];
for(int i = 0; i < strlen(s1); ++i)
a[i] = s1[i];
a[strlen(s1)] = '.';
for(int i = strlen(s1)+1, j = 0; i < size && j < strlen(s2); ++i, ++j)
a[i] = s2[j];
a[size] = '\0';
return (float)atof(a);
}
int main(void)
{
char *s1="100";
char *s2="09";
printf("%.2f\n", str2float(s1,s2));
return 0;
}
答案 4 :(得分:0)
考虑缩放小数部分并按其他人的建议添加。
char *s1="100";
char *s2="09";
float f1 = strtof(s1, (void*) NULL);
unsigned n = strlen(s2);
float f2 = strtof(s2, (void*) NULL)/powf(10, n);
return f1 + f2;
这通常已经足够了,但要深入挖掘一下。
strtof(s2, (void*) NULL)/powf(10, n);
会导致与除法的舍入,因为商,一个分数很少可以完全表示为binary32。然后添加f1 + f2
可能会产生另一个舍入。由于double rounding,总和有时不是最佳float
答案。
为了大大降低双舍入的几率,代码可以轻松使用更高的精度,如double
。
float f1 = strtof(s1, (void*) NULL);
unsigned n = strlen(s2);
double f2 = strtod(s2, (void*) NULL)/pow(10, n); // use higher precision
return f1 + f2;
或者,代码可以避免更宽的FP数学,并首先使用精确的整数数学来组合这些值,然后进行除法,只产生1个舍入。这样可以在一段时间内获得更准确的答案。
long l1 = strtol(s1, (void*) NULL, 10);
long l2 = strtol(s2, (void*) NULL, 10);
unsigned n = strlen(s2);
long p10 = pow10(n); // Trivial user TBD code
long sum = l1*p10 + l2; // Exact unless `long` overflow
return 1.0f*sum/p10; // `float` conversion exact for value up to about 1/FLT_EPSILON
如果s1
否定,则上述情况很有效。也可以s2
作为否定,除了提取数字宽度所需的代码比strlen(s2)
更多。
否则很难击败字符串连接和转换。我建议float strof()
超过double atof()
,因为1)atof()
在溢出时缺少已定义的行为,2)atof()
使用double
数学,这可能会更慢。
size_t l1 = strlen(s1);
size_t l2 = strlen(s1);
char buffer[l1 + 1 + l2 + 1]; // Or use a fixed wide buffer with test to insure fit
strcpy(buffer, s1);
buffer[l1] = '.';
strcpy(buffer + l1 + 1, s1);
return strtof(buffer, (void *) NULL);