[英]Merge two string into a float on an stm32?
I receive two string values over the UART to an stm32f3 and would like to concatenate them to a float, but I actually don't see how to do this. 我通过UART收到两个字符串值到stm32f3,并希望将它们连接到一个浮点数,但我实际上看不到如何做到这一点。 Let's do this in the example below. 我们在下面的例子中这样做。
char *s1="100";
char *s2="09"; //should result in 100.09
float x=???(s1,s2);
How can I achieve this? 我怎样才能做到这一点?
I'd convert each string to an integer, then use arithmetic: 我将每个字符串转换为整数,然后使用算术:
int whole = atoi(s1);
int frac = atoi(s2);
float x = whole + frac / powf(10, strlen(s2));
The last part computes 10^strlen(s2) because "09" means 09/100, "5" means 5/10, etc. 最后一部分计算10 ^ strlen(s2),因为“09”表示09/100,“5”表示5/10等。
If powf()
doesn't work on your system (as you said in a comment), you can use this (only good for small non-negative inputs but that's what you have): 如果powf()
在您的系统上不起作用(正如您在评论中所说),您可以使用它(仅适用于小的非负输入,但这就是您所拥有的):
float myexp10(unsigned x)
{
if (x == 0)
return 1.0;
float res = 10;
while (--x)
res *= 10;
return res;
}
One approach is to print both strings into a buffer, and then use strtod
to read a float
back: 一种方法是将两个字符串打印到缓冲区中,然后使用strtod
读取一个float
:
char buf[10];
sprintf(buf, "%.4s.%.4s", s1, s2);
float f = strtod(buf, NULL);
printf("%f\n", f);
Note that since 100.09
has no precise representation as a float
, the result would be something close to 100.089996
. 请注意,由于100.09
没有精确表示为float
,因此结果将接近100.089996
。
I would concatenate the two strings, with a dot in between, and then use strtof() to extract the float number, like this: 我会连接两个字符串,中间有一个点,然后使用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;
}
Output: 输出:
100.089996 100.089996
If that precision is not enough for you, then use strtod()
, like this: 如果你的精度不够,那么使用strtod()
,如下所示:
double result = strtod (s, NULL);
Another simple but tedious approach is to store them in char array and use atof()
for conversion as follows: 另一个简单但繁琐的方法是将它们存储在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;
}
Consider scaling the fractional part and adding as suggest by others. 考虑缩放小数部分并按其他人的建议添加。
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;
This is usually sufficient, yet to dig a bit deeper. 这通常就足够了,但还要深入挖掘一下。
strtof(s2, (void*) NULL)/powf(10, n);
incurs a rounding with the division as the quotient, a fraction, is rarely exactly representable as a binary32 . 导致与除法的舍入作为商,一个分数,很少完全可以表示为二元32 。 Then the addition f1 + f2
may incur another rounding. 然后加法f1 + f2
可能会产生另一个舍入。 The sum is sometimes then not the best float
answer due to double rounding . 由于双舍入 ,总和有时不是最好的float
答案。
To greatly reduce the chance of double rounding , code can easily use higher precision like double
. 为了大大减少双舍入的可能性,代码可以轻松地使用更高的精度,如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;
Alternatively code may avoid wider FP math and use exact integer math first to combine the values and then divide, incurring only 1 rounding. 或者,代码可以避免更宽的FP数学,并首先使用精确的整数数学来组合值然后除以,只产生1个舍入。 This will make for a more accurate answer once in a while. 这样可以偶尔获得更准确的答案。
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
The above works well if s1
is negative . 如果s1
为负数,则上述方法效果很好。 Also OK with s2
as a negative aside from more code needed to extract the digit width than strlen(s2)
. 除了strlen(s2)
提取数字宽度所需的更多代码之外,还可以使用s2
作为否定 。
Else it is hard to beat a string concatenation and convert. 否则很难击败字符串连接和转换。 I recommend float strof()
over double atof()
as 1) atof()
lacks defined behavior on overflow, 2) atof()
uses double
math, which may be slower. 我建议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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.