How to convert a float to a string without sprintf in C? - c

My code is taking a string format and compose it into a buffer (without sprintf, itoa etc).
I'm having trouble converting a float number to string, as I need to have precision of at most 7 digits with no trailing zeros. as well as convert each number in the float variable to char (but in that matter I don't need any help).
I tried several methods, all including math calculations, but nothing has brought me to the desired outcome.
Here's my code so far, but it is messy and also sometimes gives incorrect outcome. I also believe there is a more clean and less-complicated way to do it.
any help will be widely appreciated.
if (*format == 'f') {
float f = *(float*)ptrs[counter];
char str[30];
int b, c, m, k = 7, i = 0, l = 0;
int a = f;
f -= a;
while (k >= 0) {
l = pow(10, k);
m = a / l;
if (m > 0) {
break;
}
k--;
}
printf("%d", k);
for (l = k + 1; l > 0; l--) {
b = pow(10, l - 1);
c = a / b;
str[i++] = c + 48;
a %= b;
}
str[i++] = '.';
for (l = 0; l < 7; l++) {
f *= 10.0;
b = f;
str[i++] = b + 48;
f -= b;
}
for (i = 0; i < 7; i++) {
*buffer = str[i];
buffer++;
}
counter++;
str[i] = '\0';
for example:
input: float v2 =0.9372;
output: .937199
desired output: 0.9372
input: float v2 =0.25000;
output: 1.25000
desired output: 0.25

he's messy and also sometimes gives incorrect outcome
At some point given the base 2 nature of typical floating point, the programmer needs to make choices:
Short code that gets close to the correct answer.
Exact correct conversion with a fair amount of code. e.g. Function to print a double - exactly
Something in between.
With common floating point encoding, there are also issues of
Infinity
Not-a-number.
Oddities like -0.0
And how portable to make the code?
Sources of inexactness
OP's use of int limits float to about [INT_MIN...INT_MAX]. Code fails for float much outside that range. Could use long long to get some more range without a great deal of code change. Better yet research float modff(float value, float *iptr).
float f = ...;
// int a=f;
long long a=f;
Repeated use of f*=10.0 below with a fractional value in f injects a possible rounding (inexactness), at each iteration.
for(l=0;l<7;l++) {
f*=10.0;
Code makes no effort to round given that f may not be 0.0 after the fraction forming for(l=0;l<7;l++) { f*=10.0; loop. I see this as a place to improve precision. This area is also tricky as the round-up may effect many leading digits when they are 9, eventually needing a shift of the string buffer. In the 0.93721, after this loop, f was about 0.74. Since more than 0.5, a rounding would have given the answer of ".9371999" --> ".9372000".
Code aims for 7 decimal digits after the .. Values, as a decimal in code, assigned to a float match to 6 to 9 significant decimal places - which includes digits to the left of .. Expectations should not get too high.
Improvement idea
When the number of fraction digits desired is small, perform 1 scaling/round
// ASSUME f >= 0.0, (sign handling done before here)
long long a=f;
f-=a;
int int_f = round(f*pow(10, 7));
if (int_f < 10000000) {
later_printf_the_7_digits(int_f);
} else {
a++;
later_printf_the_7_digits(0);
}

Related

Failed to reuse variable in C

I'm trying to code a program that can tell apart real and fake credit card numbers using Luhn's algorithm in C, which is
Multiply every other digit by 2, starting with the number’s
second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total
modulo 10 is congruent to 0), the number is valid!
Then I coded something like this (I already declared all the functions at the top and included all the necessary libraries)
//Luhn's Algorithm
int luhn(long z)
{
int c;
return c = (sumall(z)-sumodd(z)) * 2 + sumaodd(z);
}
//sum of digits in odd position starting from the end
int sumodd(long x)
{
int a;
while(x)
{
a = a + x % 10;
x /= 100;
}
return a;
}
//sum of all digits
int sumall(long y)
{
int b;
while(y)
{
b = b + y % 10;
y /= 10;
}
return b;
}
But somehow it always gives out the wrong answer even though there's no error or bug detected. I came to notice that it works fine when my variable z stands alone, but when it's used multiple times in the same line of code with different functions, their values get messed up (in function luhn). I'm writing this to ask for any fix I can make to make my code run correctly as I intended.
I'd appreciate any help as I'm very new to this, and I'm not a native English speaker so I may have messed up some technical terms, but I hope you'd be able to understand my concerns.
sumall is wrong.
It should be sumeven from:
Add the sum to the sum of the digits that weren’t multiplied by 2.
Your sumall is summing all digits instead of the non-odd (i.e. even) digits.
You should do the * 2 inside sumodd as it should not be applied to the other [even] sum. And, it should be applied to the individual digits [vs the total sum].
Let's start with a proper definition from https://en.wikipedia.org/wiki/Luhn_algorithm
The check digit is computed as follows:
If the number already contains the check digit, drop that digit to form the "payload." The check digit is most often the last digit.
With the payload, start from the rightmost digit. Moving left, double the value of every second digit (including the rightmost digit).
Sum the digits of the resulting value in each position (using the original value where a digit did not get doubled in the previous step).
The check digit is calculated by 10 − ( s mod ⁡ 10 )
Note that if we have a credit card of 9x where x is the check digit, then the payload is 9.
The correct [odd] sum for that digit is: 9 * 2 --> 18 --> 1 + 8 --> 9
But, sumodd(9x) * 2 --> 9 * 2 --> 18
Here's what I came up with:
// digsum -- calculate sum of digits
static inline int
digsum(int digcur)
{
int sum = 0;
for (; digcur != 0; digcur /= 10)
sum += digcur % 10;
return sum;
}
// luhn -- luhn's algorithm using digits array
int
luhn(long z)
{
char digits[16] = { 0 };
// get check digit and remove from "payload"
int check_expected = z % 10;
z /= 10;
// split into digits (we use little-endian)
int digcnt = 0;
for (digcnt = 0; z != 0; ++digcnt, z /= 10)
digits[digcnt] = z % 10;
int sum = 0;
for (int digidx = 0; digidx < digcnt; ++digidx) {
int digcur = digits[digidx];
if ((digidx & 1) == 0)
sum += digsum(digcur * 2);
else
sum += digcur;
}
int check_actual = 10 - (sum % 10);
return (check_actual == check_expected);
}
// luhn -- luhn's algorithm using long directly
int
luhn2(long z)
{
// get check digit and remove from "payload"
int check_expected = z % 10;
z /= 10;
int sum = 0;
for (int digidx = 0; z != 0; ++digidx, z /= 10) {
int digcur = z % 10;
if ((digidx & 1) == 0)
sum += digsum(digcur * 2);
else
sum += digcur;
}
int check_actual = 10 - (sum % 10);
return (check_actual == check_expected);
}
You've invoked undefined behavior by not initializing a few local variables in your functions, for instance you can remove your undefined behaviour in sumodd() by initializing a to zero like so:
//sum of digits in odd position starting from the end
int sumodd(long x)
{
int a = 0; //Initialize
while(x)
{
a += x % 10; //You can "a += b" instead of "a = a + b"
x /= 100;
}
return a;
}
It's also important to note that long is only required to be a minimum of 4-bytes wide, so it is not guaranteed to be wide enough to represent a decimal-16-digit-integer. Using long long solves this problem.
Alternatively you may find this problem much easier to solve by treating your credit card number as a char[] instead of an integer type altogether, for instance if we assume a 16-digit credit card number:
int luhn(long long z){
char number[16]; //Convert CC number to array of digits and store them here
for(int c = 0; c < 16; ++c){
number[c] = z % 10; //Last digit is at number[0], first digit is at number[15]
z /= 10;
}
int sum = 0;
for(int c = 0; c < 16; c += 2){
sum += number[c] + number[c + 1] * 2; //Sum the even digits and the doubled odd digits
}
return sum;
}
...and you could skip the long long to char[] translation part altogether if you treat the credit card number as an array of digits in the whole program
This expression:
(sumall(z)-sumodd(z)) * 2 + sumall(z);
Should be:
((sumall(z)-sumodd(z)) * 2 + sumodd(z))%10;
Based on your own definition.
But how about:
(sumall(z) * 2 - sumodd(z))%10
If you're trying to be smart and base off sumall(). You don't need to call anything twice.
Also you don't initialise your local variables. You must assign variables values before using them in C.
Also you don't need the local variable c in the luhn() function. It's harmless but unnecessary.
As others mention in a real-world application we can't recommend enough that such 'codes' are held in a character array. The amount of grief caused by people using integer types to represent digit sequence 'codes' and identifiers is vast. Unless a variable represents a numerical quantity of something, don't represent it as an arithmetic type. More issue has been caused in my career by that error than people trying to use double to represent monetary amounts.
#include <stdio.h>
//sum of digits in odd position starting from the end
int sumodd(long x)
{
int a=0;
while(x)
{
a = a + x % 10;
x /= 100;
}
return a;
}
//sum of all digits
int sumall(long y)
{
int b=0;
while(y)
{
b = b + y % 10;
y /= 10;
}
return b;
}
//Luhn's Algorithm
int luhn(long z)
{
return (sumall(z)*2-sumodd(z))%10;
}
int check_luhn(long y,int expect){
int result=luhn(y);
if(result==expect){
return 0;
}
return 1;
}
int check_sumodd(long y,int expect){
int result=sumodd(y);
if(result==expect){
return 0;
}
return 1;
}
int check_sumall(long y,int expect){
int result=sumall(y);
if(result==expect){
return 0;
}
return 1;
}
int main(void) {
int errors=0;
errors+=check_sumall(1,1);
errors+=check_sumall(12,3);
errors+=check_sumall(123456789L,45);
errors+=check_sumall(4273391,4+2+7+3+3+9+1);
errors+=check_sumodd(1,1);
errors+=check_sumodd(91,1);
errors+=check_sumodd(791,8);
errors+=check_sumodd(1213191,1+1+1+1);
errors+=check_sumodd(4273391,15);
errors+=check_luhn(1234567890,((9+7+5+3+1)*2+(0+8+6+4+2))%10);
errors+=check_luhn(9264567897,((9+7+5+6+9)*2+(7+8+6+4+2))%10);
if(errors!=0){
printf("*ERRORS*\n");
}else{
printf("Success\n");
}
return 0;
}

e^x without math.h

I'm trying to find ex without using math.h. My code gives wrong anwsers when x is bigger or lower than ~±20. I tried to change all double types to long double types, but it gave some trash on input.
My code is:
#include <stdio.h>
double fabs1(double x) {
if(x >= 0){
return x;
} else {
return x*(-1);
}
}
double powerex(double x) {
double a = 1.0, e = a;
for (int n = 1; fabs1(a) > 0.001; ++n) {
a = a * x / n;
e += a;
}
return e;
}
int main(){
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
scanf("%d", &n);
for(int i = 0; i<n; i++) {
double number;
scanf("%lf", &number);
double e = powerex(number);
printf("%0.15g\n", e);
}
return 0;
}
Input:
8
0.0
1.0
-1.0
2.0
-2.0
100.0
-100.0
0.189376476361643
My output:
1
2.71825396825397
0.367857142857143
7.38899470899471
0.135379188712522
2.68811714181613e+043
-2.91375564689153e+025
1.20849374134639
Right output:
1
2.71828182845905
0.367879441171442
7.38905609893065
0.135335283236613
2.68811714181614e+43
3.72007597602084e-44
1.20849583696666
You can see that my answer for e−100 is absolutely incorrect. Why does my code output this? What can I do to improve this algorithm?
When x is negative, the sign of each term alternates. This means each successive sum switches widely in value rather than increasing more gradually when a positive power is used. This means that the loss in precision with successive terms has a large effect on the result.
To handle this, check the sign of x at the start. If it is negative, switch the sign of x to perform the calculation, then when you reach the end of the loop invert the result.
Also, you can reduce the number of iterations by using the following counterintuitive condtion:
e != e + a
On its face, it appears that this should always be true. However, the condition becomes false when the value of a is outside of the precision of the value of e, in which case adding a to e doesn't change the value of e.
double powerex(double x) {
double a = 1.0, e = a;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e + a ; ++n) {
a = a * x / n;
e += a;
}
return invert ? 1/e : e;
}
We can optimize a bit more to remove one loop iteration by initializing e with 0 instead of a, and calculating the next term at the bottom of the loop instead of the top:
double powerex(double x) {
double a = 1.0, e = 0;
int invert = x<0;
x = fabs1(x);
for (int n = 1; e != e + a ; ++n) {
e += a;
a = a * x / n;
}
return invert ? 1/e : e;
}
For values of x above one or so, you may consider to handle the integer part separately and compute powers of e by squarings. (E.g. e^9 = ((e²)²)².e takes 4 multiplies)
Indeed, the general term of the Taylor development, x^n/n! only starts to decrease after n>x (you multiply each time by x/k), so the summation takes at least x terms. On another hand, e^n can be computed in at most 2lg(n) multiplies, which is more efficient and more accurate.
So I would advise
to take the fractional part of x and use Taylor,
when the integer part is positive, multiply by e raised to that power,
when the integer part is zero, you are done,
when the integer part is negative, divide by e raised to that power.
You can even spare more by considering quarters: in the worst case (x=1), Taylor requires 18 terms before the last one becomes negligible. If you consider subtracting from x the immediately inferior multiple of 1/4 (and compensate multiplying by precomputed powers of e), the number of terms drops to 12.
E.g. e^0.8 = e^(3/4+0.05) = 2.1170000166126747 . e^0.05

Changing float numbers to int numbers in c

In some part of my program, I have an array which contains float numbers (for example 9.8, 5.0, 4.45). What I have to do is take those numbers to another array and if they are float (I mean if they have digits after the decimal point that are not zero), then multiply them by 10 enough times to make it an int value (so from the first example, after that I should have 98, 5, 445). I know it doesn't sound clear but it's hard for me to describe my problem better.
My attempt was to do this but I have errors.
for(i=0;i<size;i++)
{
if(teb[i]%10!=0)
{
while(teb[i]%1!=0)
{
teb[i]=teb[i]*10;
}
}
}
I have error: invalid operator to binary % (have float and int) and I am not sure if I can use char or similar variables.
In my opinion, you'll not be able to manage this sanely without using string formatting and then converting from string back to floating-point. I use double rather than float. This is the code I came up with, including your three test values as the first three.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static inline int all_same_as(char *str, char c)
{
while (*str != '\0')
{
if (*str++ != c)
return 0;
}
return 1;
}
static inline void zap_trailing(char *str, char c)
{
char *end = str + strlen(str);
while (end > str)
{
if (*(end - 1) != c)
return;
*--end = '\0';
}
}
static inline void zap_leading(char *str, char c)
{
char *end = str;
while (*end == c)
end++;
if (end > str)
memmove(str, end, strlen(end) + 1); /* Not memcpy()! */
}
int main(void)
{
double d[] =
{
9.8,
5.0,
4.45,
1.0,
18.0,
9.25,
8.719,
2.78128,
2721.0/1001.0,
3.14159,
355.0/113.0,
0.001234, /* Smaller */
1.2345E+13, /* Biggest */
1.2345E-13, /* Smallest */
};
enum { NUM_D = sizeof(d) / sizeof(d[0]) };
for (int i = 0; i < NUM_D; i++)
{
char buffer1[32];
snprintf(buffer1, sizeof(buffer1), "%.6f", d[i]);
char buffer2[32];
strcpy(buffer2, buffer1);
zap_leading(buffer2, ' '); /* Not needed with %.6f; was needed with %10.6f */
char *dot = strchr(buffer2, '.');
if (all_same_as(dot + 1, '0'))
*dot = '\0';
else
{
zap_trailing(dot + 1, '0');
size_t len = strlen(dot + 1);
memmove(dot, dot + 1, len + 1); /* Not memcpy()! */
}
double iv = strtod(buffer2, NULL);
printf("%8g = %8.2g = %8.3g = %10s (converted: %10s - [%s] %g)\n",
d[i], d[i], d[i], buffer1, buffer2, buffer2, iv);
}
return 0;
}
Output:
9.8 = 9.8 = 9.8 = 9.800000 (converted: 98 - [98] 98)
5 = 5 = 5 = 5.000000 (converted: 5 - [5] 5)
4.45 = 4.5 = 4.45 = 4.450000 (converted: 445 - [445] 445)
1 = 1 = 1 = 1.000000 (converted: 1 - [1] 1)
18 = 18 = 18 = 18.000000 (converted: 18 - [18] 18)
9.25 = 9.2 = 9.25 = 9.250000 (converted: 925 - [925] 925)
8.719 = 8.7 = 8.72 = 8.719000 (converted: 8719 - [8719] 8719)
2.78128 = 2.8 = 2.78 = 2.781280 (converted: 278128 - [278128] 278128)
2.71828 = 2.7 = 2.72 = 2.718282 (converted: 2718282 - [2718282] 2.71828e+06)
3.14159 = 3.1 = 3.14 = 3.141590 (converted: 314159 - [314159] 314159)
3.14159 = 3.1 = 3.14 = 3.141593 (converted: 3141593 - [3141593] 3.14159e+06)
0.001234 = 0.0012 = 0.00123 = 0.001234 (converted: 0001234 - [0001234] 1234)
1.2345e+13 = 1.2e+13 = 1.23e+13 = 12345000000000.000000 (converted: 12345000000000 - [12345000000000] 1.2345e+13)
1.2345e-13 = 1.2e-13 = 1.23e-13 = 0.000000 (converted: 0 - [0] 0)
You can make choices about how many decimal digits to support, etc. I chose to use up to 6 after the decimal point (format %.6f used with snprintf()). I included very small (1.23E-13) and very large (1.23E+13) values; the behaviour for even bigger or smaller values is similar.
I initially used %10.6f in the snprintf() statement. When I did that, values were printed with leading blanks. The zap_leading() function removes those. The code has since been revised to use %.6f and there are no leading blanks to zap. I left the code to zap leading characters in place; it could be removed too.
Most decimal fractions expressed as some finite number of digits in base 10 cannot be stored exactly in the binary floating point representations typically used in most implementations.
If you know the numbers are only supposed to be accurate to a fixed number of decimal places n, you can first multiply by 10n and round to the nearest integer. Then strip off up to n trailing zero digits.
For example, for up to 3 decimal places:
for(i=0;i<size;i++)
{
long x = round(teb[i] * 1000.0);
for (int j = 0; j < 3; j++)
{
if (x % 10 == 0)
{
x /= 10;
}
else
{
break;
}
}
teb[i] = x;
}
Normally I don't provide answers to homework problems, but since this is such a bad problem, I'm making an exception.
Before I proceed, let me say that the original problem is meaningless and impossible. Since it's impossible, there's no good way to solve it. So the program I'm going to present has a number of problems, some quite serious.
The core of the program does what the problem asks: As long as the fractional part of one of the numbers is not 0, it multiplies the number by 10. Computing "the fractional part of the number" is performed by an auxiliary function I've written, fractionalpart(). First we'll look at the program, then I'll explain its remaining problems.
#include <stdio.h>
float in[] = {9.8, 5.0, 4.45};
int out[3];
float fractionalpart(float f)
{
return f - (int)f;
}
int main()
{
int i;
for(i = 0; i < 3; i++) {
float tmp = in[i];
while(fractionalpart(tmp) > 0.001) {
tmp = tmp * 10;
}
out[i] = tmp;
}
printf("out:\n");
for(i = 0; i < 3; i++) printf("%d\n", out[i]);
}
The problems this has relate to the fact that, on an ordinary computer using ordinary floating-point representations, there is no such number as 9.8. There's no such number as 4.45, either. What you thought was the float number 4.45, for example, is represented internally as something like 4.44999980926513671875. So a "proper" version of this program would multiply it by 10 a total of twenty times, converting it to 444999980926513671875. But that number won't even fit in a 64-bit integer!
So this program cheats: it doesn't loop until the fractional part is exactly 0; it instead loops until the fractional part is less than 0.001. Where did that number come from? The answer is: nowhere, I pulled it out of the air, it seemed like a good guess. You can experiment with bigger or smaller fudge factors if you like.
The bigger problem -- and you've probably thought of this already -- is that the program assumes that the "fractional part" actually does go down to something like 0.001 or 0.0001. But that's not necessarily true! As we just saw, the number 4.45 is "really" 4.44999980926513671875 inside, so after multiplying by 10 twice, it looks like the program is going to have an integer value of 444 (not 445), and the fractional part is going to be 0.999980926513671875, which is not less than 0.001, so the program is going to keep going!
Actually, it doesn't keep going, it does get the "right answer", at least on my machine (and I think I know why), but there are probably plenty of numbers (roughly half of them, actually) where there will be an intermediate result more like 0.999 than 0.001, and this program will do the wrong thing.
I hate posting code with serious problems like this, it's very tempting to try to write an "improved" version, but it would be much messier, and really, the original question is such a horrible one that it just isn't worth it. (It would be instructive to figure out and explain why this program does seems to work, at least most of the time -- why it doesn't get confused by the occasional 0.999 value -- but I don't have time for that just now, either.)

How can I speed-up this loop?

How can I speed-up this loop (in C)?
unsigned int x = 50000000;
double a= 0.9;
double b= -0.9;
for ( unsigned int i = 1; i <= x; i++)
{
a *= 0.9; //power
b -= a/i;
}
Execution time: 14.000 s
I don't know why, but when I add this 2 lines in code, execution time is only 1.000 s.
unsigned int x = 50000000;
double a= 0.9;
double b= -0.9;
for ( unsigned int i = 1; i <= x; i++)
{
a *= 0.9; //power
a += 10e250;
a -=10e250;
b -= a/i;
}
Thanks for any help
First, the most likely reason why your code is running slower than expected is that a becomes a denormalised number. And denormalised numbers are a special case that may run a lot, lot slower. It is also possible that by adding 10^251 and subtracting it again you change a to 0 and dividing zero by anything is faster (since the result doesn't need to be calculated).
But the real speed up comes from not stupidly adding tiny, tiny numbers that have no effect whatsoever. When x = a few hundred, a will be so small that subtracting a/i from b will not make any difference. So instead of b -= a/i; you write
double old_b = b;
b -= a / i;
if (b == old_b) break;
and your time will change from seconds to much less than a millisecond.
Adding that 10e250 it exceeds the limit of digits the double variable can support and when subtracting it will always become 0. Not sure about this but multiplication should take more time than addition so it's slowing it down, ex. if you try this :
for ( unsigned int i = 1; i <= x; i++)
{
a ++; //power
b -= a/i;
}
You will see that it will run like the second time. I guess that when you add that 10e250 and after making a = 0; the multiplication with 0 is faster then with other non-zero variable.

How can I convert a float/double to ASCII without using sprintf or ftoa in C?

How can I convert a float/double to ASCII without using sprintf or ftoa in C?
I am using an embedded system.
The approach you take will depend on the possible range of values. You certainly have some internal knowledge of the possible range, and you may only be interested in conversions within a more narrow range.
So, suppose you are only interested in the integer value. In this case, I would just assign the number to an int or long, at which point the problem becomes fairly obvious.
Or, suppose the range won't include any large exponents but you are interested in several digits of fraction. To get three digits of fraction, I might say int x = f * 1000;, convert x, and then insert the decimal point as a string operation.
Failing all of the above, a float or double has a sign bit, a fraction, and an exponent. There is a hidden 1 in the fraction. (The numbers are normalized until they have no leading zeroes, at which point they do one more shift to gain an extra bit of precision.) The number is then equal to the fraction (plus a leading '1') * 2 ** exponent. With essentially all systems using the IEEE 754 representation you can just use this Wikipedia IEEE 754 page to understand the format. It's not that different from just converting an integer.
For single precision, once you get the exponent and fraction, the valueNote 1 of the number is then (frac / 223 + 1) * 2exp, or frac * 2exp - 23 + 2exp.
Here is an example that should get you started on a useful conversion:
$ cat t.c
#include <stdio.h>
void xconvert(unsigned frac)
{
if (frac) {
xconvert(frac / 10);
printf("%c", frac % 10 | '0');
}
}
void convert(unsigned i)
{
unsigned sign, exp, frac;
sign = i >> 31;
exp = (i >> (31 - 8)) - 127;
frac = i & 0x007fffff;
if (sign)
printf("-");
xconvert(frac);
printf(" * 2 ** %d + 2 ** %d\n", exp - 23, exp);
printf("\n");
}
int main(void)
{
union {
float f;
unsigned i;
} u;
u.f = 1.234e9;
convert(u.i);
return 0;
}
$ ./a.out
1252017 * 2 ** 7 + 2 ** 30
Note 1. In this case the fraction is being converted as if the binary point was on the right instead of the left, with compensating adjustments then made to the exponent and hidden bit.
#include<stdio.h>
void flot(char* p, float x)
{
int n,i=0,k=0;
n=(int)x;
while(n>0)
{
x/=10;
n=(int)x;
i++;
}
*(p+i) = '.';
x *= 10;
n = (int)x;
x = x-n;
while((n>0)||(i>k))
{
if(k == i)
k++;
*(p+k)='0'+n;
x *= 10;
n = (int)x;
x = x-n;
k++;
}
/* Null-terminated string */
*(p+k) = '\0';
}
int main()
{
float x;
char a[20]={};
char* p=&a;
printf("Enter the float value.");
scanf("%f",&x);
flot(p,x);
printf("The value=%s",p);
getchar();
return 0;
}
Even in an embedded system, you'd be hard pressed to beat the performance of ftoa. Why reinvent the wheel?

Resources