嵌入式中浮点数转字符串函数
2012年写的
原来放在开源中国社区的
还是转过来吧
AVR-GCC平台里面没有浮点转字符串
我写了个。特别的地方是末位舍入用随机舍入法
/*
<Floating number to string>
Copyright (C) <2012> <fss.sosei>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
doublerandom_round (doublex, int_fast8_t rounded_to_exp10)
{
constuint_fast8_t MAX_SIGNIFICANT_FIGURES = 5; //float floor(log10(pow(2, 23)))-1, double floor(log10(pow(2, 52)))-1
if(not isfinite(x))
{
returnx;
}
doubleabsolute_value = fabs(x);
if((floor(log10(absolute_value)) - rounded_to_exp10) >= MAX_SIGNIFICANT_FIGURES)
{
returnx;
}
doubleinteger_part, decimal_part;
decimal_part = modf(absolute_value * pow(10, -rounded_to_exp10), &integer_part);
if(decimal_part > 0.5)
{
integer_part += 1;
}
else
{
if(decimal_part == 0.5)
{
integer_part += rand() % 2;
}
}
returncopysign((integer_part + 0.1) * pow(10, rounded_to_exp10), x);
}
uint_fast8_t floating_number_to_string (doubleinput_number, uint_fast8_t decimal_digits, charnumeric_string[], uint_fast8_t array_len) //input_number range is 99999 to 0.000001. Returns the numeric string length. The random roundoff, pay attention to the random number seed.
{
constuint_fast8_t MAX_SIGNIFICANT_FIGURES = 5; //float floor(log10(2^23))-1
constuint_fast8_t MIN_DECIMAL = 6;
chartemp_string[10]; //a sign + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + a decimal), (a zero + a decimal + MIN_DECIMAL))) + '\x0'
doubleabsolute_value;
doublenum_exp10;
if(not isfinite(input_number))
{
return0;
}
if(decimal_digits > MIN_DECIMAL)
{
return0;
}
absolute_value = fabs(input_number);
num_exp10 = floor(log10(absolute_value));
if(num_exp10 >= MAX_SIGNIFICANT_FIGURES)
{ //Value ultra range error
return0;
}
doublenum_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits))); //Plus integer part
input_number = random_round(absolute_value, lround(num_tail_exp10));
absolute_value = fabs(input_number);
num_exp10 = floor(log10(absolute_value));
int_fast8_t num_int_exp10 = lround(num_exp10);
if(num_int_exp10 >= MAX_SIGNIFICANT_FIGURES)
{ //Value ultra range error
return0;
}
num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits))); //Plus integer part
int_fast8_t num_int_tail_exp10 = lround(num_tail_exp10);
if(num_int_tail_exp10 > num_int_exp10)
{
num_exp10 = num_tail_exp10;
num_int_exp10 = num_int_tail_exp10;
}
uint_fast8_t num_count = num_int_exp10 - num_int_tail_exp10 + 1;
doubleintermediate_number = absolute_value * pow(10, -num_exp10);
doubledigital_character[num_count];
for(int_fast8_t i = 0; i < num_count; ++i)
{
intermediate_number = modf(intermediate_number, &digital_character[i]) * 10;
}
int_fast8_t i = 0;
uint_fast8_t n;
if((input_number < 0 ? 1 : 0) == 1)
{
temp_string[i] = '-'; ++i;
}
int_fast8_t j = 0;
if(num_int_exp10 >= 0)
{
n = i + num_int_exp10;
while(i <= n)
{
temp_string[i] = (char)(lround(digital_character[j]) + 0x30); //0x30 == '0'
++i;
++j;
}
if((num_int_tail_exp10 < 0 ? 1 : 0) == 1)
{
temp_string[i] = '.'; ++i;
}
n = i + abs(num_int_tail_exp10);
while(i < n)
{
temp_string[i] = (char)(lround(digital_character[j]) + 0x30); //0x30 == '0'
++i;
++j;
}
}
else
{
temp_string[i] = '0'; ++i;
temp_string[i] = '.'; ++i;
n = i + (-1 - num_int_exp10);
while(i < n)
{
temp_string[i] = '0'; ++i;
}
n = i + (num_int_exp10 - num_int_tail_exp10);
while(i <= n)
{
temp_string[i] = (char)(lround(digital_character[j]) + 0x30); //0x30 == '0'
++i;
++j;
}
}
temp_string[i] = '\x0';
n = i;
if((n + 1) > array_len)
{
return0;
}
for(i=0; i <= n; ++i)
{
numeric_string[i] = temp_string[i];
}
returnn; //Returns the numeric string length
}