gpt4 book ai didi

c - 将有理数表示为四舍五入的小数

转载 作者:太空宇宙 更新时间:2023-11-03 23:50:02 38 4
gpt4 key购买 nike

使用 gmp 库和有理数 (mpq_t),我试图打印出有理数作为小数部分,达到给定的精度(小数点后的数字)。

我目前的方法是写入一个 char 缓冲区,对缓冲区中的数字进行四舍五入,然后打印出来。它有效,但我觉得我觉得它太复杂了,即:

  • 除法计算整数部分
  • 通过将余数乘以 10^(prec+1) 再除以计算小数部分
  • 将两者放入char 缓冲区
  • 从缓冲区的末尾返回,对数字进行四舍五入
  • 打印出这个号码以及沿途收集的所有额外信息
    • 可选减号
    • 溢出(例如,精度为 3 的 0.9999 实际上是 1)
    • 处理额外的零(例如 0.00001)

问题:

有更好的方法吗?更简单?我完全错过了什么?

请注意,有理数的分子和分母可以“任意”大。

这里是相关代码,mpz1mpz2都是mpz_t类型并且已经初始化,我转换的有理在mpq1:

编辑:此代码中至少有一个错误,但我不想找到它,因为我重新编写了它。

/* We might need to insert a digit between the sign
* and the rest of the number:
* deal with the sign explicitly
*/
int negative = 0;
if (mpz_sgn(mpq_numref(mpq1)) == -1) /* negative number */
negative = 1;

/* Calculate the integer part and the remainder */
mpz_tdiv_qr(mpz1, mpz2, mpq_numref(mpq1), mpq_denref(mpq1));
if (mpz_cmp_ui(mpz2, 0) == 0) { /* remainder is 0 */
gmp_printf("%Zd", mpz1);
return;
}

/* What is the maximum possible length of the decimal fraction? */
size_t max_len =
mpz_sizeinbase(mpz1, 10) /* length of the string in digits */
+ 1 /* '\0' terminator */
/* + 1 possible minus sign: dealing with it explicitly */
/* + 1 decimal point: dealing with it explicitly */
+ real_precision + 1; /* precision and the extra digit */

/* Prepare the buffer for the string */
/* ... */
/* block of sufficient size at char *str */
char *end = str;
end += gmp_sprintf(end, "%Zd", mpz1);
char *dec_point = end;

/* Calculate the fractional part and write it to the buffer:
* to round correctly, we need to know one more digit than
* the precision we are aiming at
*/
mpz_abs(mpz2, mpz2);
mpz_ui_pow_ui(mpz1, 10, real_precision + 1);
mpz_mul(mpz2, mpz2, mpz1);
mpz_tdiv_q(mpz2, mpz2, mpq_denref(mpq1));
end += gmp_sprintf(end, "%Zd", mpz2);
size_t extra_zeros = real_precision + 1 - (end - dec_point);

char *p = end - 1; /* position of the extra digit */
/* Do we need to round up or not? */
int roundup = 0;
if (*p > '4')
roundup = 1;

/* Propagate the round up back the string of digits */
while (roundup && p != str) {
--p;
++*p;
if (*p > '9')
*p = '0';
else
roundup = 0;
}

/* Move end back to the first non-zero of the fractional part */
p = end - 2; /* position of the last significant digit */
while (*p == '0' && p != dec_point - 1)
--p;
end = p + 1; /* the new end */

/* Output the number */
if (negative) /* minus sign */
putc('-', stdout);

if (roundup) /* overflow */
putc('1', stdout);

/* Integer part */
p = str;
while (p != dec_point) {
putc(*p, stdout);
++p;
}
if (p == end) /* There is no fractional part after rounding */
return;

/* Fractional part */
putc('.', stdout);
while (extra_zeros-- != 0)
putc('0', stdout);
while (p != end) {
putc(*p, stdout);
++p;
}

最佳答案

如果您想将一个无符号的有理数舍入到最接近的整数,您需要加上 0.5,然后只显示整数部分。

对于小数点后的 1 位数字,您需要添加 0.05。

对于小数点后的 2 位数字,您将添加 0.005。

对于小数点后的 n 位,您将添加 5/( 10**(n+1) )

关于c - 将有理数表示为四舍五入的小数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22245457/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com