- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我已经为 floating point problem 找到了一些解决方法在 PHP 中:
php.ini 设置 precision = 14
342349.23 - 341765.07 = 584.15999999992 // floating point problem
php.ini 设置,比方说 precision = 8
342349.23 - 341765.07 = 584.16 // voila!
演示:http://codepad.org/r7o086sS
有多糟糕?
<强>1。如果我只需要精确的 2 位数计算(金钱),我可以依靠这个解决方案吗?
<强>2。如果不能,当这个解决方案失败时,你能给我一个明确的例子吗?
编辑:3.哪个php.ini.precision值最适合两位数,金钱计算
@Baba 回答很好,但他在测试中使用了 precision=20
,precision=6
...所以我仍然不确定它是否会起作用或不是。
请考虑以下内容:
假设 precision = 8
,我唯一要做的就是加法 +
和减法 -
A + B = C
A - B = C
问题 1:对于 0..999999.99 之间的数字,精确解决方法是否会失败,其中 A 和 B 是带小数位的数字?如果是这样,请给我一个例子。
简单的测试就可以完成工作:
// if it fails what if I use 9,10,11 ???
// **how to find when it fails??? **
ini_set('precision', 8);
for($a=0;$a<999999.99;$a+=0.01) {
for($b=0;$b<999999.99;$b+=0.01) {
// mind I don't need to test comparision (round($a-$b,2) == ($a-$b))
echo ($a + $b).','.($a - $b)." vs ";
echo round($a + $b, 2).','.round($a - $b, 2)."\n";
}
}
but obviously 99999999 * 2
is too big job so I can't run this test
问题 2:当精度变通方法失败时如何估计/计算?没有这么疯狂的测试? 是否有任何数学*,直接的答案?如何计算是否会失败?
*我不需要知道浮点计算的工作原理,但是如果您知道精度以及 A 和 B 的范围,当解决方法失败时
请注意我真的知道 cents 和 bcmath 是最好的解决方案。但我仍然不确定减法和加法的解决方法是否会失败
最佳答案
许多人认为浮点运算是一门深奥的学科。这是相当令人惊讶的,因为 float 在计算机系统中无处不在。大多数小数没有二进制小数的精确表示,因此会进行一些舍入。一个好的开始是 What Every Computer Scientist Should Know About Floating-Point Arithmetic
Can I rely on this solution if I need just precise 2 digits calculations (money)?
如果您需要精确的 2 位数 那么答案是否 您不能使用 php 精度设置来确定 2 位数 小数即使您不打算处理大于 10^6 的数字
,也始终如此。
在计算过程中,如果长度小于8,则有可能增加精度长度
If not can you provide me a clear example when this solutions fails?
ini_set('precision', 8); // your precision
$a = 5.88 ; // cost of 1kg
$q = 2.49 ;// User buys 2.49 kg
$b = $a * 0.01 ; // 10% Discount only on first kg ;
echo ($a * $q) - $b;
输出
14.5824 <---- not precise 2 digits calculations even if precision is 8
Which php.ini.precision value suits best two digits, money calculations?
精度和货币计算是两种不同的东西......使用 PHP 精度作为财务计算或浮点长度的基础不是一个好主意
Lest 使用 bcmath
、number_format
和简单的 minus
一起运行一些示例
基础
$a = 342349.23;
$b = 341765.07;
示例 A
ini_set('precision', 20); // set to 20
echo $a - $b, PHP_EOL;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), PHP_EOL;
输出
584.15999999997438863
584.15999999999996817 <----- Round having a party
584.16
584.15 <-------- here is 15 because precision value is 20
示例 B
ini_set('precision', 14); // change to 14
echo $a - $b, PHP_EOL;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), PHP_EOL;
输出
584.15999999997
584.16
584.16
584.16 <-------- at 14 it changed to 16
示例 C
ini_set('precision', 6); // change to 6
echo $a - $b, PHP_EOL;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), PHP_EOL;
输出
584.16
584.16
584.16
584.00 <--- at 6 it changed to 00
示例 D
ini_set('precision', 3); // change to 3
echo $a - $b, PHP_EOL;
echo floatval(round($a - $b, 2)), PHP_EOL;
echo number_format($a - $b, 2), PHP_EOL;
echo bcsub($a, $b, 2), PHP_EOL;
输出
584
584
584.16 <-------------------------------- They only consistent value
0.00 <--- at 3 .. everything is gone
忘掉 float ,只计算 cents
然后除以 100
如果为时已晚只需简单地使用 number_format
它看起来一致对我来说。
Question 1: Is precision workaround gonna fail for numbers between 0..999999.99, where A and B is a number with decimal places? If so please provide me an example
从 0
到 999999.99
以 0.01
的增量大约是 99,999,999
你的循环的组合可能性是9,999,999,800,000,000
我真的不认为有人会愿意为您运行这样的测试。
由于 float 是精度有限的二进制数,因此尝试设置 precision
对确保准确性的影响有限这是一个简单的测试:
ini_set('precision', 8);
$a = 0.19;
$b = 0.16;
$c = 0.01;
$d = 0.01;
$e = 0.01;
$f = 0.01;
$g = 0.01;
$h = $a + $b + $c + $d + $e + $f + $g;
echo "Total: " , $h , PHP_EOL;
$i = $h-$a;
$i = $i-$b;
$i = $i-$c;
$i = $i-$d;
$i = $i-$e;
$i = $i-$f;
$i = $i-$g;
echo $i , PHP_EOL;
输出
Total: 0.4
1.0408341E-17 <--- am sure you would expect 0.00 here ;
尝试
echo round($i,2) , PHP_EOL;
echo number_format($i,2) , PHP_EOL;
输出
0
0.00 <------ still confirms number_format is most accurate to maintain 2 digit
Question 2: How to estimate/calculate when precision workaround fails? Without such crazy tests? Is there any mathematical*, straight answer for it? How to calculate is gonna to fail or not?
事实仍然存在Floating Point有Accuracy Problems但对于数学解决方案,您可以查看
i don't need to know floating point calculations works, but when workaround fails if you know precision, and range of A and B
不确定那句话是什么意思:)
关于php - 我可以依靠 PHP php.ini 精度解决浮点问题吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14587290/
@Cacheable在同一类中方法调用无效 上述图片中,同一个类中genLiveBullets()方法调用同类中的queryLiveByRoom()方法,这样即便标识了Cacheable标签,
目录 @Transaction注解导致动态切换更改数据库失效 使用场景 遇到问题 解决 @Transaction
@RequestBody不能class类型匹配 在首次第一次尝试使用@RequestBody注解 开始加载字符串使用post提交(貌似只能post),加Json数据格式传输的时候,
目录 @Autowired注入static接口问题 @Autowired自动注入普通service很方便 但是如果注入static修饰的serv
目录 @RequestBody部分属性丢失 问题描述 JavaBean实现 Controller实现
目录 解决@PathVariable参数接收不完整的问题 今天遇到的问题是: 解决办法: @PathVariable接受的参
这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚。后来终于找到了原因。 如果你也出现了这种情况,可以从下面开始排查。 1、特性 先来了解一下@Trans
概述: ? 1
场景: 在处理定时任务时,由于这几个方法都是静态方法,在aop的切面中使用@Around注解,进行监控方法调用是否有异常。 发现aop没有生效。 代码如下:
最近做项目的时候 用户提出要上传大图片 一张图片有可能十几兆 本来用的第三方的上传控件 有限制图片上传大小的设置 以前设置的是2M&nb
我已经实现了这个SCIM reference code在我们的应用程序中。 我实现的代码确实通过了此postman link中存在的所有用户测试集合。 。我的 SCIM Api 也被 Azure 接受
我一直对“然后”不被等待的行为感到困扰,我明白其原因。然而,我仍然需要绕过它。这是我的用例。 doWork(family) { return doWork1(family)
我正在尝试查找 channel 中的消息是否仍然存在,但是,我不确定如何解决 promise ,查看其他答案和文档,我可以看到它可能是通过函数实现的,但我是不完全确定如何去做。我希望能在这方面获得一些
我有以下情况: 同一工作区中的 2 个 Eclipse 项目:Apa 和 Bepa(为简洁起见,使用化名)。 Apa 项目引用(包括)Bepa 项目。 我在 Bepa 有一个类 X,具有公共(publ
这个问题已经有答案了: Why am I getting a NoClassDefFoundError in Java? (31 个回答) 已关闭 6 年前。 我正在努力学习 spring。所以我输入
我正在写一个小游戏,屏幕上有许多圆圈在移动。 我在两个线程中管理圈子,如下所示: public void run() { int stepCount = 0; int dx;
我在使用 Sympy 求解方程时遇到问题。当我运行代码时,例如: 打印(校正(10)) 我希望它打印一个数字 f。相反,它给我错误:执行中止。 def correction(r): from
好吧,我制作的每个页面都有这个问题。我不确定我做错了什么,但我所有的页面都不适用于所有分辨率。可能是因为我使用的是宽屏?大声笑我不确定,但在小于宽屏分辨率的情况下,它永远不会看起来正确。它的某些部分你
我正在尝试像这样进行一个非常简单的文化 srting 检查 if(culture.ToUpper() == "ES-ES" || "IT-IT") { //do something } else
Closed. This question is off-topic. It is not currently accepting answers. Learn more。 想改进这个问题吗?Upda
我是一名优秀的程序员,十分优秀!