test01 发表于 2012-9-19 15:58:14

贡献一个开源的浮点数转字符串函数,附带随机舍入函数

本帖最后由 弘毅 于 2017-11-3 12:24 编辑

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

double random_round (double x, int_fast8_t rounded_to_exp10)
{
const uint_fast8_t MAX_SIGNIFICANT_FIGURES = 5;//float floor(log10(pow(2, 23)))-1, double floor(log10(pow(2, 52)))-1

if (not isfinite(x))
{
    return x;
}
double absolute_value = fabs(x);
if ((floor(log10(absolute_value)) - rounded_to_exp10) >= MAX_SIGNIFICANT_FIGURES)
{
    return x;
}

double integer_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;
    }
}
return copysign((integer_part + 0.1) * pow(10, rounded_to_exp10), x);
}

uint_fast8_t floating_number_to_string (double input_number, uint_fast8_t decimal_digits, char numeric_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.
{
const uint_fast8_t MAX_SIGNIFICANT_FIGURES = 5;//float floor(log10(2^23))-1
const uint_fast8_t MIN_DECIMAL = 6;

char temp_string;//a sign + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + a decimal), (a zero + a decimal + MIN_DECIMAL))) + '\x0'
double absolute_value;
double num_exp10;

if (not isfinite(input_number))
{
    return 0;
}
if (decimal_digits > MIN_DECIMAL)
{
    return 0;
}

absolute_value = fabs(input_number);
num_exp10 = floor(log10(absolute_value));
if (num_exp10 >= MAX_SIGNIFICANT_FIGURES)
{//Value ultra range error
    return 0;
}
double num_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
    return 0;
}
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;
double intermediate_number = absolute_value * pow(10, -num_exp10);
double digital_character;
for (int_fast8_t i = 0; i < num_count; ++i)
{
    intermediate_number = modf(intermediate_number, &digital_character) * 10;
}

int_fast8_t i = 0;
uint_fast8_t n;
if ((input_number < 0 ? 1 : 0) == 1)
{
    temp_string = '-'; ++i;
}
int_fast8_t j = 0;
if (num_int_exp10 >= 0)
{
    n = i + num_int_exp10;
    while(i <= n)
    {
      temp_string = (char)(lround(digital_character) + 0x30);//0x30 == '0'
      ++i;
      ++j;
    }
    if ((num_int_tail_exp10 < 0 ? 1 : 0) == 1)
    {
      temp_string = '.'; ++i;
    }
    n = i + abs(num_int_tail_exp10);
    while(i < n)
    {
      temp_string = (char)(lround(digital_character) + 0x30);//0x30 == '0'
      ++i;
      ++j;
    }
}
else
{
    temp_string = '0'; ++i;
    temp_string = '.'; ++i;
    n = i + (-1 - num_int_exp10);
    while(i < n)
    {
      temp_string = '0'; ++i;
    }
    n = i + (num_int_exp10 - num_int_tail_exp10);
    while(i <= n)
    {
      temp_string = (char)(lround(digital_character) + 0x30);//0x30 == '0'
      ++i;
      ++j;
    }
}
temp_string = '\x0';
n = i;
if ((n + 1) > array_len)
{
    return 0;
}
for (i=0; i <= n; ++i)
{
    numeric_string = temp_string;
}
return n;//Returns the numeric string length
}
==========================
纯C11草案标准写的
有什么使用问题欢迎留言

test01 发表于 2012-9-21 17:56:24

哈哈,会贴代码了

test01 发表于 2012-10-13 02:47:53

为更方便大家应用,变更了开源许可证
页: [1]
查看完整版本: 贡献一个开源的浮点数转字符串函数,附带随机舍入函数