JS实现浮点数精确舍入小数点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS实现浮点数精确舍入小数点相关的知识,希望对你有一定的参考价值。

参考技术A 舍入是使用数字时最常见的操作之一。

这里有几个对数字进行舍入的内建函数:

//向下舍入:3.1变成3,-1.1变成-2

//向上舍入:3.1变成4,-1.1变成-1

//向最近的整数舍入:3.1变成3,3.6变成4,中间值3.5变成4

//移除小数点后的所有内容而没有舍入:3.1变成3,-1.1变成-1

这些函数涵盖了处理数字小数部分的所有可能方法。但是,如果我们想将数字舍入到小数点后 n 位改怎么办?

例如,我们有 1.2345 ,并且想把它舍入到小数点后两位,仅得到 1.23 。

有两种方法可以实现这个需求:

1.乘除法

例如,要将数字舍入到小数点后两位,我们可以将数字乘以 100 (或更大的 10 的整数次幂),调用舍入函数,然后再将其除回。

2.函数 toFixed(n) 将数字舍入到小数点后 n 位,并以字符串形式返回结果。

这会向上或向下舍入到最接近的值,类似于Math.round():

请注意 tofixed 的结果是一个字符串。如果小数部分比需要的短,则在结尾添加 0 :

我们可以使用一元加号或 Number() 调用,将其转换为数字: +num.toFixed(5) ;

将浮点数舍入到 N 个小数位

【中文标题】将浮点数舍入到 N 个小数位【英文标题】:Mathematically round float to N decimal places 【发布时间】:2018-10-07 07:57:35 【问题描述】:

我想将浮点数/双精度数四舍五入到 n 位小数。但不是在印刷中,而是在一般情况下。 例如:用户的输入是:2.3891 3,所以输出应该是 2.389 或者如果用户输入 5.98441 4,输出应该是:5.9844

#include <stdio.h>
#include <math.h>

int main () 

float num;
int decimals;

scanf("%f%d", &num, &decimals); //5.2381 2

int res = num; // res = 5

int power = 1;
int i = 0;
for(i = 0; i < decimals; i++)
    power*=10; // 1 * 10 * 10

int num3 = num * power; // num3 = 523
int num2 = num3 % power;//

float a = num2*1.0 / power*1.0;
// float a = 23*1.0/13.0;
printf("%f %d\n", a, power);

a = res + a;

printf("%f", a);

return 0;

作为这里的输出,我得到:2.390000。我不想有这些零,也不想使用固定的 %.2f。我错过了什么?

【问题讨论】:

你所要求的是不可能的。浮点数没有小数位。 @melpomene 准确地说是“二进制浮点数”,因为decimal floating point numbers 确实存在。但你是对的。 您可以使用printf("%g", a);,这将是remove trailing zeroes。 始终使用double(忘记float 存在)。 double roundn(double x, int n) double b = pow(10, n); int c = (x + 0.5) * b; /*mind overflow*/ return c / b; @UlrichEckhardt:唯一比float 更好的是空间要求。 double 更精确,double(通常)更快,double 避免自动转换为 double。每个浮点变量 4 个额外字节不会对您的可执行文件产生影响(当然,除非您需要巨大的数组)。在float x = 42, y; y = x * 2; 中有两种自动转换:首先,在乘法之前,x 被转换为双精度;之后结果被转换为浮点数。 【参考方案1】:

一般来说,这个任务是不可能的,因为 IEEE 754 转换是二进制浮点数或双精度浮点数的表示。所以上面的行scanf("%f%d", &amp;num, &amp;decimals); //5.2381 2 确实将十进制(以 10 为底)数字转换为二进制浮点数,并且这种转换通常不是 exaxt,因为您只有有限的位数。 您可以减少位数(二进制),但这不是在十进制系统中定义的。 打印一个浮点(双)精度数字,由于将二进制转换为十进制浮点计算,存在第二个不精度。

【讨论】:

【参考方案2】:

您在这里做两件事:1) 计算一个数字的四舍五入值,以及 2) 打印该数字。

计算四舍五入的值

你做得很好。请注意,在将 float 隐式转换为 int 时,C 会进行截断,而不是舍入,因此:

float f = 1.9;
int i = f;

i 设置为1,而不是2。在您的情况下,如果您的输入是“1.229 2”,那么您计算的值是 1.22,而不是 1.23。这可能是您想要的,但可能不是。如果您想将 off 舍入而不是 趋近于零,您可能需要更改:

int num3 = num * power;

到:

int num3 = 0.5 + num * power;

打印四舍五入的值

一旦您计算出该值,您就可以打印它。如果您只想打印四舍五入的小数位数,可以使用printf() 的精度字段,如下所示:

printf("%.*f\n", decimals, a);

【讨论】:

实际上,如果只是输出表示需要四舍五入,那么请使用您正确支持的打印技术; printf() 函数将正确舍入。【参考方案3】:

一般来说,这是不可能的。 C 和 C++ 中的浮点数最终以基数、尾数、符号和指数的形式指定。

十进制浮点数以 10 为底。在现代硬件的实践中极为罕见。一些早期的计算硬件(如 1946 年创建的 ENIAC)支持十进制浮点。然而,这样的表示在现代硬件中相当少见。

现代硬件上最常见的浮点表示使用2(即二进制)为基数。二进制浮点不能表示所有小数。尝试使用2 的负幂之和来表示十进制值0.1(如1/21/41/8 等)。你会发现0.1 的表示涉及十进制的无穷级数。原因类似于分数1/3 不能用有限的小数位表示(即0.33333....,其中数字3 永远重复)。

无理值(如sqrt(2.0)pi 等)也不能以任何有限位数的数字基数精确表示。所以不可能设计出一个固定和有限大小的浮点类型来精确地保存这些值。

【讨论】:

十进制在现代硬件中并不是“非常”罕见的。它不存在于常见的个人使用计算机中。例如,IBM 制造用于商业/工业用途的十进制硬件。

以上是关于JS实现浮点数精确舍入小数点的主要内容,如果未能解决你的问题,请参考以下文章

如何舍入一个浮点数?

将浮点数舍入到 N 个小数位

怎么精确提取一个浮点数的小数部分?

解决JS浮点数(小数)计算加减乘除的BUG

浮点数怎么表示精确度?

如何在不进行任何舍入的情况下将浮点数转换为小数点后 4 位?