极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10407|回复: 3

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

[复制链接]
发表于 2012-9-19 15:58:14 | 显示全部楼层 |阅读模式
本帖最后由 弘毅 于 2017-11-3 12:24 编辑
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

  4. double random_round (double x, int_fast8_t rounded_to_exp10)
  5. {
  6.   const uint_fast8_t MAX_SIGNIFICANT_FIGURES = 5;  //float floor(log10(pow(2, 23)))-1, double floor(log10(pow(2, 52)))-1
  7.   
  8.   if (not isfinite(x))
  9.   {
  10.     return x;
  11.   }
  12.   double absolute_value = fabs(x);
  13.   if ((floor(log10(absolute_value)) - rounded_to_exp10) >= MAX_SIGNIFICANT_FIGURES)
  14.   {
  15.     return x;
  16.   }
  17.   
  18.   double integer_part, decimal_part;
  19.   decimal_part = modf(absolute_value * pow(10, -rounded_to_exp10), &integer_part);
  20.   if(decimal_part > 0.5)
  21.   {
  22.     integer_part += 1;
  23.   }
  24.   else
  25.   {
  26.     if(decimal_part == 0.5)
  27.     {
  28.       integer_part += rand() % 2;
  29.     }
  30.   }
  31.   return copysign((integer_part + 0.1) * pow(10, rounded_to_exp10), x);
  32. }

  33. 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.
  34. {
  35.   const uint_fast8_t MAX_SIGNIFICANT_FIGURES = 5;  //float floor(log10(2^23))-1
  36.   const uint_fast8_t MIN_DECIMAL = 6;
  37.   
  38.   char temp_string[10];  //a sign + (decimal_digits == 0 ? MAX_SIGNIFICANT_FIGURES : max((MAX_SIGNIFICANT_FIGURES + a decimal), (a zero + a decimal + MIN_DECIMAL))) + '\x0'
  39.   double absolute_value;
  40.   double num_exp10;

  41.   if (not isfinite(input_number))
  42.   {
  43.     return 0;
  44.   }
  45.   if (decimal_digits > MIN_DECIMAL)
  46.   {
  47.     return 0;
  48.   }
  49.   
  50.   absolute_value = fabs(input_number);
  51.   num_exp10 = floor(log10(absolute_value));
  52.   if (num_exp10 >= MAX_SIGNIFICANT_FIGURES)
  53.   {  //Value ultra range error
  54.     return 0;
  55.   }
  56.   double num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
  57.   input_number = random_round(absolute_value, lround(num_tail_exp10));
  58.   
  59.   absolute_value = fabs(input_number);
  60.   num_exp10 = floor(log10(absolute_value));
  61.   int_fast8_t num_int_exp10 = lround(num_exp10);
  62.   if (num_int_exp10 >= MAX_SIGNIFICANT_FIGURES)
  63.   {  //Value ultra range error
  64.     return 0;
  65.   }
  66.   num_tail_exp10 = fmax((num_exp10 + 1 - MAX_SIGNIFICANT_FIGURES), (-((int_fast8_t)decimal_digits)));  //Plus integer part
  67.   int_fast8_t num_int_tail_exp10 = lround(num_tail_exp10);
  68.   if (num_int_tail_exp10 > num_int_exp10)
  69.   {
  70.     num_exp10 = num_tail_exp10;
  71.     num_int_exp10 = num_int_tail_exp10;
  72.   }
  73.   
  74.   uint_fast8_t num_count = num_int_exp10 - num_int_tail_exp10 + 1;
  75.   double intermediate_number = absolute_value * pow(10, -num_exp10);
  76.   double digital_character[num_count];
  77.   for (int_fast8_t i = 0; i < num_count; ++i)
  78.   {
  79.     intermediate_number = modf(intermediate_number, &digital_character[i]) * 10;
  80.   }
  81.   
  82.   int_fast8_t i = 0;
  83.   uint_fast8_t n;
  84.   if ((input_number < 0 ? 1 : 0) == 1)
  85.   {
  86.     temp_string[i] = '-'; ++i;
  87.   }
  88.   int_fast8_t j = 0;
  89.   if (num_int_exp10 >= 0)
  90.   {
  91.     n = i + num_int_exp10;
  92.     while(i <= n)
  93.     {
  94.       temp_string[i] = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
  95.       ++i;
  96.       ++j;
  97.     }
  98.     if ((num_int_tail_exp10 < 0 ? 1 : 0) == 1)
  99.     {
  100.       temp_string[i] = '.'; ++i;
  101.     }
  102.     n = i + abs(num_int_tail_exp10);
  103.     while(i < n)
  104.     {
  105.       temp_string[i] = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
  106.       ++i;
  107.       ++j;
  108.     }
  109.   }
  110.   else
  111.   {
  112.     temp_string[i] = '0'; ++i;
  113.     temp_string[i] = '.'; ++i;
  114.     n = i + (-1 - num_int_exp10);
  115.     while(i < n)
  116.     {
  117.       temp_string[i] = '0'; ++i;
  118.     }
  119.     n = i + (num_int_exp10 - num_int_tail_exp10);
  120.     while(i <= n)
  121.     {
  122.       temp_string[i] = (char)(lround(digital_character[j]) + 0x30);  //0x30 == '0'
  123.       ++i;
  124.       ++j;
  125.     }
  126.   }
  127.   temp_string[i] = '\x0';
  128.   n = i;
  129.   if ((n + 1) > array_len)
  130.   {
  131.     return 0;
  132.   }
  133.   for (i=0; i <= n; ++i)
  134.   {
  135.     numeric_string[i] = temp_string[i];
  136.   }
  137.   return n;  //Returns the numeric string length
  138. }
复制代码

==========================
纯C11草案标准写的
有什么使用问题欢迎留言
回复

使用道具 举报

 楼主| 发表于 2012-9-21 17:56:24 | 显示全部楼层
哈哈,会贴代码了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-13 02:47:53 | 显示全部楼层
为更方便大家应用,变更了开源许可证
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-28 03:03 , Processed in 0.052904 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表