最大是多少?我应该为浮点数显示多少位小数? (PHP)

发布于 2024-10-04 12:38:31 字数 1341 浏览 0 评论 0原文

我仍然无法得到准确的结果。最大是多少?如果我希望它尽可能准确,我应该显示小数位数?

一些代码(准备复制粘贴和测试):

// Test with 5 decimals 
$a = 0.00001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>';
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/><br/>';

/* Output:
0.00000
0.000000
0.00000
0.000000
0.00000000000000000000
0.00000
0.000000000000000000000
*/

// Test with 4 decimals
$a = 0.0001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>'; // wtf? this outputs 0 too?
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/>';

/* Output:
0.00020
0.000200
0.00020
0.000200
0.00000000000000000000
0.00020
0.000200000000000000010
*/

我应该推断答案是 4 ???但我仍然有一个评论编辑问题

:我认为没有人理解我的测试。我知道浮点数不准确。但一件事是 1 != 0.98990123,另一件事是 1 != 0.0000。如果我将 bc* 函数中的精度设置为 4,我预计会得到至少 0.9899(如果完美答案为 1),而不是 0.0000。一件事“对于无限精度而言并不完全准确”,另一件事“完全无用”。

编辑2:@Michael Borgwardt 有解决方案

I still can't get accurate results. What is the max. amount of decimals I should display if I want it to be as accurate as possible?

Some code (ready to be copy-pasted and tested):

// Test with 5 decimals 
$a = 0.00001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>';
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/><br/>';

/* Output:
0.00000
0.000000
0.00000
0.000000
0.00000000000000000000
0.00000
0.000000000000000000000
*/

// Test with 4 decimals
$a = 0.0001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>'; // wtf? this outputs 0 too?
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/>';

/* Output:
0.00020
0.000200
0.00020
0.000200
0.00000000000000000000
0.00020
0.000200000000000000010
*/

Should I infer that the answer is 4 ??? But I still have a problem in the line with a comment

Edit: I don't think anyone understood my tests. I know floats are inaccurate. But one thing is 1 != 0.98990123, and other thing is 1 != 0.0000. If I set 4 as the precision in the bc* function, I expect to get at least 0.9899 (if the perfect answer were 1), not 0.0000. One thing is 'not perfectly accurate for infinite precision', other thing is 'completely useless'.

Edit 2: @Michael Borgwardt has the solution

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏末染殇 2024-10-11 12:38:31

最大是多少?如果我希望它尽可能准确,我应该显示小数位数?

您的问题始于尝试从浮点计算中获取准确的值。由于表示错误,您通常无法从浮点计算中获得准确的值。值 0.0001 无法用二进制浮点数精确表示,因此实际存储的值将与 0.0001 略有不同,这已经给您带来了不准确性。您应该预料到最低有效数字将不准确。显示更多的小数并不会使您的计算更加准确 - 它只会使固有的不准确性更加明显。

如果您需要准确性,您应该使用不同的数据类型(bcadd 确实接受字符串,但从浮点到字符串的转换仍然会导致不准确)或更改您的程序以允许与精确答案略有不同的答案。

如果您只想显示有用的答案,您可以按照对您的应用程序有意义的精度显示它。如果您正在计算设置烤箱烹饪火鸡的温度,那么将答案四舍五入到几个有效数字应该没问题。如果您正在进行科学计算,您可能希望以 3、4 或更多有效数字显示答案。如果您需要 100% 的准确性,那么您需要重新考虑您的设计。

What is the max. amount of decimals I should display if I want it to be as accurate as possible?

Your problem starts with trying to get accurate values from floating point calculations. You cannot in general get accurate values from floating point calculations because of representation errors. The value 0.0001 cannot be represented exactly in binary floating point so the actual stored value will differ slightly from 0.0001 and that already gives you an inaccuracy. You should expect that the least significant digits will be inaccurate. Displaying more decimals doesn't make your calculation any more accurate - it just makes the inherent inaccuracies more visible.

If you need accuracy, you should either use a different datatype (bcadd does accept strings, but the conversion from a float to a string can still introduce an inaccuracy) or change your program to allow for answers that are slightly different from the precise answer.

If you just want to display a useful answer you can display it to the precision that makes sense for your application. If you are calculating the temperature to set an oven to cook a turkey then rounding the answer to a couple of significant figures should be fine. If you are doing scientific calculations you might want to display answers with 3, 4 or more significant figures. If you need 100% accuracy then you need to rethink your design.

梦境 2024-10-11 12:38:31

“bcadd”需要三个参数。前两个是表示左操作数和右操作数的字符串,以及一个表示结果中的小数位的整数。该函数输出一个字符串。尝试在第五个结果回显中使用字符串值而不是整数。

另外,关于浮点数的精度(来自 PHP.net):

浮点数的大小取决于平台,尽管最大 ~1.8e308 且精度大约为 14 位十进制数字是常见值(64 位 IEEE格式)。

"bcadd" requires three arguments. The first two are strings representing the left and right operands and one integer representing the decimal places in the result. This function outputs a string. Try using a string value instead of integers in your fifth result echo.

Also, regarding the precision of floating point numbers (from PHP.net):

The size of a float is platform-dependent, although a maximum of ~1.8e308 with a precision of roughly 14 decimal digits is a common value (the 64 bit IEEE format).

抚笙 2024-10-11 12:38:31

问题的主要原因是您使用的是浮点文字。当代码被编译或解释并转换为二进制分数时,这会导致舍入错误。

到那时,你就已经输了——使用 bc 数学函数没有帮助。要正确使用它们,您必须使用字符串文字:

echo bcadd('0.00001','0.00001',20);

将打印:

0.00002000000000000000

A major cause of your problem is that you're using float literals. That causes a rounding error when the code is compiled or interpreted and converted to a binary fraction.

At that point, you've already lost - using the bc math functions won't help. To use those correctly, you have to use string literals:

echo bcadd('0.00001','0.00001',20);

Will print:

0.00002000000000000000
烧了回忆取暖 2024-10-11 12:38:31

尝试使用 BCMath 库。它基本上将数字存储为字符串,但允许您对其进行算术运算。

处理非常大或非常小的数字

Try using the BCMath library. It basically stores the number as a string but allows you to do arithmetic to it.

Handling Very Large or Very Small Numbers

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文