可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How do I convert 30.8365146 into two integers, 30 and 8365146, for example, in Arduino or C?
This problem faces me when I try to send GPS data via XBee series 1 which don't allow to transmit fraction numbers, so I decided to split the data into two parts. How can I do this?
I have tried something like this:
double num=30.233;
int a,b;
a = floor(num);
b = (num-a) * pow(10,3);
The output is 30
and 232
! The output is not 30 and 233. Why and how can I fix it?
回答1:
double value = 30.8365146;
int left_part, right_part;
char buffer[50];
sprintf(buffer, "%lf", value);
sscanf(buffer, "%d.%d", &left_part, &right_part);
and you will get left/right parts separately stored in integers.
P.S. the other solution is to just multiply your number by some power of 10 and send as an integer.
回答2:
You can output the integer to a char array using sprintf, then replace the '.'
with a space and read back two integers using sscanf.
回答3:
I did it for float, using double as temporary:
int fract(float raw) {
static int digits = std::numeric_limits<double>::digits10 - std::numeric_limits<float>::digits10 - 1;
float intpart;
double fract = static_cast<double>(modf(raw, &intpart));
fract = fract*pow(10, digits - 1);
return floor(fract);
}
I imagine that you could use quadruple-precision floating-point format to achieve the same for double: libquadmath.
回答4:
The 30 can just be extracted by rounding down (floor(x) in math.h).
The numbers behind the decimal point are a bit more tricky, since the number is most likely stored as a binary number internally, this might not translate nicely into the number you're looking for, especially if floating point-math is involved. You're best bet would probably be to convert the number to a string, and then extract the data from that string.
回答5:
As in the comments, you need to keep track of the decimal places. You can't do a direct conversion to integer. A bit of code that would do something like this:
#include <stdio.h>
#include <math.h>
#define PLACES 3
void extract(double x)
{
char buf[PLACES+10];
int a, b;
sprintf(buf, "%.*f", PLACES, x);
sscanf(buf, "%d.%d", &a, &b);
int n = (int) pow(10, PLACES);
printf("Number : %.*f\n", PLACES, x);
printf(" Integer : %d\n", a);
printf(" Fractional part: %d over %d\n", b, n);
}
int main()
{
extract(1.1128);
extract(20.0);
extract(300.000512);
}
Produces:
Number : 1.113
Integer : 1
Fractional part: 113 over 1000
Number : 20.000
Integer : 20
Fractional part: 0 over 1000
Number : 300.001
Integer : 300
Fractional part: 1 over 1000
回答6:
What about using floor() to get the integer value and
num % 1 (modulo arithmetic) to get the decimal component?
Then you could multiply the decimal component by a multiple of 10 and round.
This would also give you control over how many decimal places you send, if that is limited in your comm. standard.
Would that work?
#include <math.h>
integer_part = floor(num);
decimal_part = fmod(num,1)*10^whatever;