krowinski / bcmath-extended Goto Github PK
View Code? Open in Web Editor NEWExtends php BCMath lib for missing functions like floor, ceil, round, abs, min, max, rand for big numbers. Also wraps existing BCMath functions.
License: MIT License
Extends php BCMath lib for missing functions like floor, ceil, round, abs, min, max, rand for big numbers. Also wraps existing BCMath functions.
License: MIT License
Please provide the following details.
Steps required to reproduce the problem.
hexdec
method, for example: BC::hexdec('0x300000000d2c12440c4310c20c2428c20c8330cc0ca318ca0cc330cc0c230806')
Expected Result.
Actual Result.
PHP Deprecated: Invalid characters passed for attempted conversion, these have been ignored in /<path>/vendor/krowinski/bcmath-extended/src/BCMathExtended/BC.php on line 438
Currently using version 6.0.0
Is it possible to make getDecimalsLengthFromNumber()
method public
instead of private
?
In an integration test of a project I'm working on, there's a case where I'd like to do:
$this->assertEquals(BC::round($expectedValue, BC::getDecimalsLengthFromNumber($actualValue), $actualValue);
I need to do this in that test, in order to ensure that a third-party system is returning properly rounded values. The inputs in the test are generated dynamically, and the third-party system outputs a varying number of decimals, depending on the size of the number.
Here are some example inputs and outputs to illustrate this:
--- Expected (inputs generated in the test)
+++ Actual (outputs returned from the third-party system)
@@ @@
-'1399454.22512577'
+'1399454.2251258'
-'959960482.27973165'
+'959960482.27973'
Please provide the following details.
I am using BC::roundDown()
on my responses to always round down specific fields to a specific decimal place. Now let's say we have in a for me realistic scenario of 16000 BC::roundDown()
operations on my response. It's fine if they are all raw and not already rounded. But what if they are already? In my case the values coming cache and other sources are already rounded to 2 decimals. So why should I run BC::roundDown()
again, but at the same time I can not be sure that the source always gives me formatted values?
I did 3 different solutions with 10 million values to be round:
preg_match
BC::roundDown
as we currently do:Simple validation with explode takes 2.6 seconds to run.
Using preg_match takes 0.8 seconds to run
Just do what we do now and just run BC::roundDown takes 76 seconds to run
So projected on my current project, I can drop another 10 ms at least from the response generation. And in total reduce CPU time if we can add this simple validation to the library where it makes sense.
$case = 2;
$testString = '1234.123';
$start = microtime(true);
for ($i = 0; $i < 16000; ++$i) {
switch ($case) {
case 0:
$elements = explode('.', $testString);
$elementsCount = count($elements);
if ($elementsCount === 1) {
continue 2;
}
if (strlen(end($elements)) <= 2) {
// Match
}
break;
case 1:
if (preg_match("/\d+(\.\d{1,2})?$/", $testString)) {
// Match
}
break;
case 2:
BC::roundDown($testString, 2);
break;
}
}
dump(microtime(true) - $start);
I can see some document saying that the return may be int/float.
But I think BC methods should always return string instead.
do you think we need to type hinting string for the return?
As of 7.2 float can be passed to bcmod but they don't return correct values (IMO)
I created bug for this in https://bugs.php.net/bug.php?id=76287 but it was commented as documentation issue not a bug.
bcmod() doesn't use floor() but rather truncates towards zero,
which is also defined this way for POSIX fmod(), so that the
result always has the same sign as the dividend. Therefore, this
is not a bug, but rather a documentation issue.
But I still will use floor not truncated for fmod in this lib.
Reference: https://stackoverflow.com/questions/21902817/convert-float-to-plain-string-representation
At the moment, we can't put sci-float val into arg.
Hoping to support it by adding the reference function to parsing sci-float first.
private function convertFloat($floatAsString)
{
$norm = strval(floatval($floatAsString));
if (($e = strrchr($norm, 'E')) === false) {
return $norm;
}
return number_format($norm, -intval(substr($e, 1)), '.', '');
}
Please provide the following details.
Steps required to reproduce the problem.
BC::roundUp("1.11111111", 2) = "1.12"
Please provide the following details.
Steps required to reproduce the problem.
For testing I used another library https://php-decimal.io. Following code compares the result of BC::pow
and $decimal->pow
public function testNegativeExponentBCVsDecimal()
{
$base = '1.005';
$exp = '-120.12345678';
โ
$v1Dec = new Decimal($base);
$v1 = $v1Dec->pow(new Decimal($exp))->toString();
$v1_old = BC::pow($base, $exp);
printf("\n$v1\n$v1_old");
}
Expected Result.
0.5492944034820568190269179210
Actual Result.
0.5499712716356165
So the BC version will start deviating after the third digit after the comma. It does not matter how high you set the scale, it will always be incorrect after a few digits.
Please provide the following details.
Steps required to reproduce the problem.
Expected Result.
Actual Result.
Fatal error: Uncaught TypeError: BCMathExtended\BC::*(): Argument #* ($*) must be of type string, null given
See this demo with bcadd
vs BC::add
: https://phpsandbox.io/n/orange-snow-okeg-2feqa
And this Stackoverflow for explanation as to why this happens : https://stackoverflow.com/questions/45600400/php7-methods-with-a-scalar-type-declaration-refuse-to-type-juggle-null-values
PS: obviously, I don't call the lib with an explicit null
on purpose ; it's the result of a very long chain of events in a big legacy project...
Here is the functions I am using:
function roundDown($value, $places) : float
{
$mult = pow(10, abs($places));
return $places < 0 ?
floor($value / $mult) * $mult :
floor($value * $mult) / $mult;
}
function roundUp($value, $places) : float
{
$mult = pow(10, abs($places));
return $places < 0 ?
ceil($value / $mult) * $mult :
ceil($value * $mult) / $mult;
}
But it is not in BC.
I need a BC version and hope it will be added in this project.
PHP does support max(array) and min(array). But this project doesn't support.
I like this project very much and it adds lots of missing methods from BC.
but the built-in bc is procedural style. and this project is using static OOP.
we still need to use bcadd/bcsub/bcmul/... in procedural style, while for max/min/avg we can use static OOP style. So I would like to suggest adding add/sub/mul/,,, those existing methods in this project. and let this project be more powerful.
As title, I think we can implement these logic operator features are as follows:
or
, xor
and and
operators.I can't understand why would you enforce the trimming of the trailing zeroes after the decimal point?
A global setting, or something simmilar, that can disable this would be nice. Additionally, the class is not extendable at all, as you are calling the static methods with the self::
instead of the static::
caller.
Please provide the following details.
Steps required to reproduce the problem.
<input type="number" />
field+
or -
in the exponent part (valid format). e.g. 3.456e11
.BC::convertScientificNotationToString(...)
on it.Expected Result.
"345600000000"
Actual Result.
"3.45611"
The problem is that convertScientificNotationToString(int|string|float $number)
uses an uncomplete regex to test for a scientific notation. Please check the formal php documentation. It states:
LNUM [0-9]+
DNUM ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})
[+-]?
[+-]?
Consider deprecating/dropping support for php 5.x and 7.0 in the next major version as they officially reached end of life some months ago. See: https://www.php.net/supported-versions.php
Why? Stay up to date & have all the nice things that php7.1+ offers.
Please provide the following details.
Steps required to reproduce the problem.
not required
Expected Result.
not required
Actual Result.
not required
All public methods should have consistent parameter type hints. I guess it should be int|float|string
. Some methods are missing this doc block type hints and because of this, editors and static code analyzers are complaining/marking uses with warnings/errors.
Please also check that all public methods have a correct return type hint.
Please provide the following details.
Steps required to reproduce the problem.
Expected Result.
Actual Result.
A number of methods pass null as scale parameter to bcmath-functions. However, bcmath interprets this as 0. As a user of this library I expect that passing no scale parameter will result in using the scale set by bcscale or the configured scale value in php.ini, not using scale 0.
This problem exists with the following functions:
Bug other functions can give wrong results due to this bug too:
E.g. the following test fails:
self::assertSame('7.20', BC::min('7.30', '7.20'));
- Unit\BCTest::shouldMin
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-7.20
+7.30
Please provide the following details.
Would it be possible to implement a bcmath function that can calculate pow
with arbitrary precision, using a fractional exponent?
Maybe https://stackoverflow.com/questions/33486170/php-how-to-raise-number-to-tiny-fractional-exponent is a solution?
Steps required to reproduce the problem.
Expected Result.
Something like this.
1.08379838673
Actual Result.
The bcpow function only supports integer exponents. Try using pow instead.
Please provide the following details.
Steps required to reproduce the problem.
$value = '1.1259';
$scale = 2;
var_dump(round($value, $scale, PHP_ROUND_HALF_EVEN)); // float(1.13)
var_dump(BC::roundHalfEven($value, $scale)); // string(4) "1.12"
Expected Result.
Actual Result.
string(4) "1.12"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.