Coder Social home page Coder Social logo

math's Introduction

Brick\Math

A PHP library to work with arbitrary precision numbers.

Build Status Coverage Status Latest Stable Version Total Downloads License

Installation

This library is installable via Composer:

composer require brick/math

Requirements

This library requires PHP 8.1 or later.

For PHP 8.0 compatibility, you can use version 0.11. For PHP 7.4, you can use version 0.10. For PHP 7.1, 7.2 & 7.3, you can use version 0.9. Note that these PHP versions are EOL and not supported anymore. If you're still using one of these PHP versions, you should consider upgrading as soon as possible.

Although the library can work seamlessly on any PHP installation, it is highly recommended that you install the GMP or BCMath extension to speed up calculations. The fastest available calculator implementation will be automatically selected at runtime.

Project status & release process

While this library is still under development, it is well tested and considered stable enough to use in production environments.

The current releases are numbered 0.x.y. When a non-breaking change is introduced (adding new methods, optimizing existing code, etc.), y is incremented.

When a breaking change is introduced, a new 0.x version cycle is always started.

It is therefore safe to lock your project to a given release cycle, such as ^0.12.

If you need to upgrade to a newer release cycle, check the release history for a list of changes introduced by each further 0.x.0 version.

Package contents

This library provides the following public classes in the Brick\Math namespace:

  • BigNumber: base class for BigInteger, BigDecimal and BigRational
  • BigInteger: represents an arbitrary-precision integer number.
  • BigDecimal: represents an arbitrary-precision decimal number.
  • BigRational: represents an arbitrary-precision rational number (fraction).
  • RoundingMode: enum representing all available rounding modes.

And the following exceptions in the Brick\Math\Exception namespace:

Overview

Instantiation

The constructors of the classes are not public, you must use a factory method to obtain an instance.

All classes provide an of() factory method that accepts any of the following types:

  • BigNumber instances
  • int numbers
  • float numbers
  • string representations of integer, decimal and rational numbers

Example:

BigInteger::of(123546);
BigInteger::of('9999999999999999999999999999999999999999999');

BigDecimal::of(1.2);
BigDecimal::of('9.99999999999999999999999999999999999999999999');

BigRational::of('2/3');
BigRational::of('1.1'); // 11/10

Note that all of() methods accept all the representations above, as long as it can be safely converted to the current type:

BigInteger::of('1.00'); // 1
BigInteger::of('1.01'); // RoundingNecessaryException

BigDecimal::of('1/8'); // 0.125
BigDecimal::of('1/3'); // RoundingNecessaryException

Note about native integers: instantiating from an int is safe as long as you don't exceed the maximum value for your platform (PHP_INT_MAX), in which case it would be transparently converted to float by PHP without notice, and could result in a loss of information. In doubt, prefer instantiating from a string, which supports an unlimited numbers of digits:

echo BigInteger::of(999999999999999999999); // 1000000000000000000000
echo BigInteger::of('999999999999999999999'); // 999999999999999999999

Note about floating-point values: instantiating from a float might be unsafe, as floating-point values are imprecise by design, and could result in a loss of information. Always prefer instantiating from a string, which supports an unlimited number of digits:

echo BigDecimal::of(1.99999999999999999999); // 2
echo BigDecimal::of('1.99999999999999999999'); // 1.99999999999999999999

Immutability & chaining

The BigInteger, BigDecimal and BigRational classes are immutable: their value never changes, so that they can be safely passed around. All methods that return a BigInteger, BigDecimal or BigRational return a new object, leaving the original object unaffected:

$ten = BigInteger::of(10);

echo $ten->plus(5); // 15
echo $ten->multipliedBy(3); // 30

The methods can be chained for better readability:

echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45

Parameter types

All methods that accept a number: plus(), minus(), multipliedBy(), etc. accept the same types as of(). For example, given the following number:

$integer = BigInteger::of(123);

The following lines are equivalent:

$integer->multipliedBy(123);
$integer->multipliedBy('123');
$integer->multipliedBy($integer);

Just like of(), other types of BigNumber are acceptable, as long as they can be safely converted to the current type:

echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.0')); // 4
echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // RoundingNecessaryException
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0

Division & rounding

BigInteger

By default, dividing a BigInteger returns the exact result of the division, or throws an exception if the remainder of the division is not zero:

echo BigInteger::of(999)->dividedBy(3); // 333
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException

You can pass an optional rounding mode to round the result, if necessary:

echo BigInteger::of(1000)->dividedBy(3, RoundingMode::DOWN); // 333
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::UP); // 334

If you're into quotients and remainders, there are methods for this, too:

echo BigInteger::of(1000)->quotient(3); // 333
echo BigInteger::of(1000)->remainder(3); // 1

You can even get both at the same time:

[$quotient, $remainder] = BigInteger::of(1000)->quotientAndRemainder(3);
BigDecimal

Dividing a BigDecimal always requires a scale to be specified. If the exact result of the division does not fit in the given scale, a rounding mode must be provided.

echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
echo BigDecimal::of(1)->dividedBy('8', 2); // RoundingNecessaryException
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_DOWN); // 0.12
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_UP); // 0.13

If you know that the division yields a finite number of decimals places, you can use exactlyDividedBy(), which will automatically compute the required scale to fit the result, or throw an exception if the division yields an infinite repeating decimal:

echo BigDecimal::of(1)->exactlyDividedBy(256); // 0.00390625
echo BigDecimal::of(1)->exactlyDividedBy(11); // RoundingNecessaryException
BigRational

The result of the division of a BigRational can always be represented exactly:

echo BigRational::of('123/456')->dividedBy('7'); // 123/3192
echo BigRational::of('123/456')->dividedBy('9/8'); // 984/4104

Bitwise operations

BigInteger supports bitwise operations:

  • and()
  • or()
  • xor()
  • not()

and bit shifting:

  • shiftedLeft()
  • shiftedRight()

Serialization

BigInteger, BigDecimal and BigRational can be safely serialized on a machine and unserialized on another, even if these machines do not share the same set of PHP extensions.

For example, serializing on a machine with GMP support and unserializing on a machine that does not have this extension installed will still work as expected.

math's People

Contributors

alexeyshockov avatar benmorel avatar dasprid avatar grahamcampbell avatar olsavmic avatar peter279k avatar reedy avatar sebastiendug avatar tomtomsen avatar trowbotham avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

math's Issues

Add some generic number type when you don't know if the result will be `int` or `decimal`

As far as I know, the bc library (and gmp too I think) works on arbitrary precision numbers and doesn't discriminate between int or float/decimal. I am re-writing a TypeScript library to PHP and now need to use some BigNumber's math, but am not sure whether the calculations should be done on Integers or Decimals.

It would be great if there was some generic number type that would automatically convert to BigInt if there's no decimals after the calculation or BigDecimal otherwise.

Does this support scientific notation?

The reason I'm asking, I'm trying to do some Unit Conversions using the https://github.com/PhpUnitsOfMeasure/php-units-of-measure library, and unfortunately with the accuracy I'm trying to have, the floats they are currently using isn't enough. I'm looking at maybe converting their library to use this library for the numbers. However for the SI Units, it's all notated in scientific notation... which I could manually convert, but why if I don't have to?

Thanks!

Fatal error: Maximum execution time of 30 seconds exceeded

PHP Version 7.4.15

$fromBase = BrickBigInteger::fromBase("bd58e8d59e95cf0617f358b4106467af2ed6489d61af4e147e3582d8206888325ac52717344c4ad80b1e05507809ed19016a4d389a1d62e26724d52190a140768630e3c5b88f205b72f84727b265cf867321e50f29a48257da043a86a6db99d3fff1b2b390ea9f683a55f60061d963e59aae38eecc56b3b23816d923da2154b5b8581ab65e9151f003c43231bb7b0f95d4866adf04da2e4986cf843c9999f351ff915cf73355e0ad397544242c383bb7850320af30e696da693e535f2e99b4eed034f85f0b02f28fda140235b759d41a2fbddfb70271715f90f927414dd9a8565047597fd2b932ec8ee070e888342ef47c195575782a5aa4be1040dd89fad605e522e66f9ad4f97c2e473e91801111c237972525f14247924f87fdcc9305716ce9c6cd5f1166eae642081e5de0fbfe02d87154178cc5eae4ebb31879eab82da400d266391ccb1bc6e6986c4c497b7cb025c5910e95fd053238b68f305955fa0df4ba2e34fdef4749f511c622b19c476f398d1518bdcf734afa88779c0550b0b65e42043c400040086279689764af9767753ebc9dae54cc7036f43222fe9189749a06a3825d1eff02a0a5a219f4740800d1dc94843470912f1f98a211b2a303fe33b867c34e4eb2d880b3cbe14a90541401d9c0bab7c1d09f47b9d0ff77484577a7c13f888350d39d29c03cccd62fe7ad6d3afda08564522b7c8ff0ae9963cfe3", 16);


Call Stack

1 | 0.0052 | 393368 | {main}( ) | .../index.php:0
2 | 0.0132 | 397736 | require( '/var/www/html/config/bootstrap.php ) | .../index.php:3
3 | 0.5040 | 2868464 | Brick\Math\BigInteger::fromBase( $number = '....', $base = 16 ) | .../bootstrap.php:21
4 | 0.5143 | 3005048 | Brick\Math\Internal\Calculator\NativeCalculator->fromBase( $number = '....', $b = '9' ) | .../Calculator.php:443
7 | 31.4177 | 3006616 | Brick\Math\Internal\Calculator\NativeCalculator->doMul( $a = '....', $b = '9' ) | .../NativeCalculator.php:130
8 | 31.4649 | 3007936 | Brick\Math\Internal\Calculator\NativeCalculator->add( $a = '.....', $b = '20885513040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' ) | .../NativeCalculator.php:511
9 | 31.4649 | 3007936 | Brick\Math\Internal\Calculator\NativeCalculator->doAdd( $a = '....', $b = '20885513040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' )


This only happens when using a real hosting provider or a docker image. Works fine when using the php's built in server.

Why to have "Big" in all class names?

Hi again! 🙂

I'm getting curious what was the reason why are all Brick\Math classes called "Big"Something. Yep, they are primarily used for big numbers. I have opened code which is using Brick\Math just to provide concepts or integer, decimal and rational (no big numbers).

There is no straightforward representation of rational or decimal numbers in plain PHP. For example 1/3 or .3. I care a lot about types and semantics. int or float number sub-sets does not match any of meaningful number subsets like integers, decimal numbers and rational numbers.

Brick\Math represents concept of decimal, rational and integers exactly. I would consider it good-enough reason to name these classes as Decimal, Rational and Integer.

What is your point of view? I would be especially happy to hear arguments against this proposed change. Thanks!

Integration with Doctrine

Hi,

First, thank you for all the effort spent on this library. There are many libraries for arbitrary precision maths in PHP, and this one is by far the best I've come across.

I'm not sure if this is the best place to ask this question, so my apologies if it isn't.

How might I integrate this library with Doctrine? I'm mostly only interested in the BigDecimal type. I've tried creating an Embeddable or a custom type, however I'm struggling to define the appropriate scale. In Doctrine, one can define a mapping to a MySQL decimal type as such:

    /**
     * @Column(type="decimal", name="total", precision=19, scale=4)
     */
    protected $total;

I'm trying to map the above field to a BigDecimal($value, 4). Basically, I'm able to define a custom type, though unless I hardcode the scale (or use BigDecimal::of(), as is done here) to a specific number, I'm unable to dynamically set the scale on a per-case basis (e.g. one field with a scale of 4, and another with a different scale).

Thank you!

Implements the Serializable interface, which is deprecated

When using PHP 8.1:

Deprecated: Brick\Math\BigInteger implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in /app/vendor/brick/math/src/BigInteger.php on line 22

Deprecated: Brick\Math\BigDecimal implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in /app/vendor/brick/math/src/BigDecimal.php on line 17

More info: https://php.watch/versions/8.1/serializable-deprecated

Thank you for fixing!

Issue with dividedBy and MultipliedBy?

Hi!
I'm currently trying to convert this following formula to my code

% increase = (total - (total - current)) ÷ total × 100

However it somehow give different result when I wrote dividedBy then multipliedBy and multipliedBy then dividedBy

$tc & $cc is BigDecimal Object
For testing : 
if $tc = 10 and $cc = 1, the result should be 10
if $tc = 10 and $cc = 2, the result should be 20

BigDecimal::of($tc->minus($tc->minus($cc)))->dividedBy($tc, 0, RoundingMode::HALF_UP)->multipliedBy('100') // always return 0 (incorrect result)
BigDecimal::of($tc->minus($tc->minus($cc)))->multipliedBy('100')->dividedBy($tc, 0, RoundingMode::HALF_UP) // correct result returned

I'm not quite sure if this behavior is intended or there is incorrect implementation from my end..

Thank you for creating this amazingly useful library though 😄

Rounding error on exactlyDividedBy()

I had something like this:

BigDecimal::one()->exactlyDividedBy(BigDecimal::of(10));

And I was getting:
PHP Fatal error: Uncaught Brick\Math\Exception\RoundingNecessaryException: Rounding is necessary to represent the result of the operation at this scale.

Which I didn't expect because 1/10 doesn't yield infinite decimals.

After some digging, I found out that some piece of my code had changed de bcscale to 8 and Brick\Math\Internal\Calculator\BcMathCalculator::mod was returning '0.00000000' instead of '0', which caused Brick\Math\Internal\Calculator::divRound() to throw the exception since '0.00000000' === '0' is false of course (lines 435, 449).

I found out that since php7.2 (I was using php7.4), the bcmod function accepts a third parameter for the scale, which I think maybe could be used to prevent an error like this? Although I see the library still supports php7.1, so maybe it's not possible

Could you remove the final keyword from your BigDecimal, BigInteger and BigRational classes?

I would prefer to use your awesome math classes.
But one of my use cases requires me to have extendability.
Could you remove the final keyword from your BigDecimal, BigInteger and BigRational classes.
And make all private fields protected.

Also dependency injection is a requirement.
But all your constructors are private.

Could you explain to me why you have closed off your entire class for extension?
And are u willing use dependency injection to have a separate stage of object creation?

Output a BigRational in decimal form with period

It could be nice to provide a way to output a BigRational as a decimal number with its decimal period.

For example, 10/3 could be output as 3.(3), while 171/70 could be output as 2.4(428571).
(Not sure about the correct format here, is there a standard for this?)

divisionBy scale issue!

I've found interesting thing about it
http://screencloud.net/v/7zDR

(string) $rate->plus(1)->power($nper)->minus(1)->dividedBy('0.010', null, Brick\Math\RoundingMode::CEILING); // works correctly!
(string) $rate->plus(1)->power($nper)->minus(1)->dividedBy('0.01', null, Brick\Math\RoundingMode::CEILING) ; // incorrect comma should be shifted but nothing happened! 

exactlyDividedBy throwing a RoundingNecessaryException.

The 'exactlyDividedBy' method is throwing a RoundingNecessaryException.
I'm guessing this shouldn't happen or am i missing something?

Example:
BigDecimal::of(1)->exactlyDividedBy('1927.27900');

PS, love your work and im using it in every PHP project i create.

RFC: add `getPrecision` method.

Hi,

Similar to getScale, would you be on favor of adding a method getPrecision?
I want to perform app side validation on BigDecimal before passing to Postgres numeric fields, and getPrecision would make that easier.

Thanks!

Feature Request: Implement lisachenko/z-engine

lisachenko/z-engine is a great library that allows you to for example have objects comparable or use mathematical operations on them.

Example what would be possible:

<?php
var_dump(new BigInteger(5) > new BigInteger(1)); // true
var_dump(new BigInteger(10) + new BigInteger(3)); // BigInteger with value 13

It could be implemented as an optional dependency instead of a hardwired one.

New Psalm issues

The latest build highlighted yet another kind of Psalm issue:

ERROR: MoreSpecificReturnType - src/BigNumber.php:159:16 - The declared return type 'Brick\Math\BigNumber&static' for Brick\Math\BigNumber::min is more specific than the inferred return type 'Brick\Math\BigNumber' (see https://psalm.dev/070)
* @ return static The minimum value.
ERROR: LessSpecificReturnStatement - src/BigNumber.php:182:16 - The type 'Brick\Math\BigNumber' is more general than the declared return type 'Brick\Math\BigNumber&static' for Brick\Math\BigNumber::min (see https://psalm.dev/129)
return $min;
...

https://travis-ci.org/github/brick/math/jobs/675371330

@alexeyshockov Could you please have a look?

How to accept any scale without rounding

Hi,

Is there anyway to accept any resulting scale without doing an rounding?
Best with an example:

BigDecimal::of('1')->dividedBy('1000');

will result in RoundingNecessaryException, but really i want to allow the scale to be set to whatever is necessary. i.e i want to result to be:

BigDecimal::ofUnscaledValue(1, 3)

My work around at the moment is:

BigRational::of('1/1000')->toBigDecimal();

which gets me the result i want.

Thanks!

The given value ".1200" does not represent a valid number.

It seems that decimal strings that do not start with an 0 char can not be parsed.

Example code

$a = BigDecimal::of('.1200')->serialize();
assert('1200:4' === $a);

Expected response

> true

Actual response

Brick/Math/Exception/NumberFormatException with message 'The given value ".1200" does not represent a valid number.'

Context

MS Sql Server returns money columns as strings, but does not prepend a 0 on values less then 1. I was hoping I could push these strings straight into BigDecimal.

Workaround

For now I am using this workaround:

if (is_string($value) && '.' === $value[0]) {
    $value = '0' . $value;
}
return BigDecimal::of($value);

BigDecimal and BigInteger should not be final classes.

Great library. I'm trying to extend the BigDecimal classes for my use case. I'm doing some cryptography programming which uses hexadecimals. So my version of BigDecimal should support base 16.

It's not possible to extend your class because the class is declared as final.

Perhaps you can remove the final keyword.

Rounding bug, or am I just dumb?

BigDecimal::of(0.02485333644)->toScale(4, RoundingMode::HALF_UP)->toFloat(), // 0.0249 <- correct
BigDecimal::of(0.02485333644)->toScale(3, RoundingMode::HALF_UP)->toFloat(), // 0.025 <- correct
BigDecimal::of(0.02485333644)->toScale(2, RoundingMode::HALF_UP)->toFloat(), // 0.02 <- WHAT???
BigDecimal::of(0.0248)->toScale(2, RoundingMode::HALF_UP)->toFloat(), // 0.02 <- WHY???
BigDecimal::of(0.025)->toScale(2, RoundingMode::HALF_UP)->toFloat(), // 0.03 <- CORRECT

What is going on here? Is it only looking at the 4 and rounding down instead of rounding 5, then 8, then 4(5)?
This is not the behaviour I was expecting.
I am using version 0.9.3, which has no code differences with 0.10.0, the latest version at the time of writing this, so it's not like I'm running an outdated, buggy version.

PHP 5.4 Support

I've forked the repo and replaced all unsupported syntax with 5.4 supported implementations.

Would you mind creating a branch to be maintained separately?

GitHub CI instead of Travis

@BenMorel, what do you think about possibility of this move?

GitHub CI integrates nice into the process, you can see checks success/failure more granularly, and also it's a possibility to report errors back directly to a PR, as a comments (like CS errors, Psalm errors, etc.).

The only issue I'm seeing currently is that the build takes a lot of time, and GitHub has limited time a project. It's 2000 minutes/month currently, so if a build takes about 10 minutes... We have kinda 200 build per month, that should be enough, considering commits/PR rate to this repo.

Another option is to switch partially, like move all the quick checks (code style, Psalm, etc.) to GitHub CI, and leave heavy unit tests in Travis. But I think it's better to keep this as the last option.

Implement `__debugInfo` magic method

If I use Symfony's VarDumper to write out a BigDecimal (e.g. with psysh or whatever when debugging), all we see is something like this:

> $transaction->getAmountDecimal()
= Brick\Math\BigDecimal {#7066}

If BigDecimal implemented the __debugInfo() magic method, it would be visible.

For example, if we add this:

    public function __debugInfo(): ?array
    {
        return [
            'value' => $this->value,
            'scale' => $this->scale,
        ];
    }

We instead see in the output:

> $transaction->getAmountDecimal()
= Brick\Math\BigDecimal {#7064
    value: "10000",
    scale: 2,
  }

Would there be any negative side effects to this?

1.0.0 release?

Hello,

Do you know when a 1.0.0 of this library will be released?

Thanks!

Accept hexadecimal input

Is it possible to add support for hexadecimal input to avoid additional conversion?

Example: BigDecimal::of('0x5208')->multipliedBy('0x59682f08');

Adding additional methods to match the Java API.

Would you be accepting a patch which adds "aliases" for the existing methods to make the API match the Java BigDecimal API? For example an add(...) method which just forwards to plus(...).

The reasoning is that the math classes are already fairly closely modeled to the Java ones, and making the API more in line with the Java one would make them easier to use for everyone coming from Java.

Adding arbitrary Length Numbers to MathPHP

I'm one of the developers of MathPHP, and I'm in the process of adding Arbitrary Length numbers to that library. It looks like you're interested in math, so If you would like to help out, please stop by and take a look (https://github.com/markrogoyski/math-php/). I've just finalized an arbitrary length Integer object, and plan of working on floating point numbers soon. One difference I see is my library supports and number base up to 256 since everything is stored as binary strings. It can also support any "alphabet" that the user specifies for their number base.

I've just stumbled on this package and thought I'd reach out.

BigDecimal::of(0.00001)->getScale() is 6

BigDecimal::of(0.0001)->getScale() is 4
BigDecimal::of(0.00001)->getScale() is 6
i find that "BigDecimal::of(0.00001)" the value is 10, and the scale is 6.
Can the value is 1, and the scale is 5 ?

BigComplex

Hi,

Are you open to adding BigComplex to the package? Any current plans or previous decisions regarding this?

Add SQRT feature

As title, I think this math package should add this sqrt feature.

Instantiating from floats

The docs/readme states:

Note about floating-point values: instantiating from a float might be unsafe, as floating-point values are imprecise by design, and could result in a loss of information. Always prefer instantiating from a string, which supports an unlimited number of digits...

I'm looking to implement this library throughout my existing application, but am using float types in my method signatures. According to the above, it sounds like I should either pass in strings instead, or convert the floats to strings.

So one of?

BigDecimal::of(strval($x));
BigDecimal::of((string) $x);

EDIT: I should mention that the floats I'm working with are provided from another library. In other words, I am not creating these values myself, but instead performing calculations on generated ones.

Psalm issues

The latest build (with no code changes) highlighted Psalm issues; these may have been introduced by a new version of Psalm (?):

ERROR: ImpureByReferenceAssignment - src/BigDecimal.php:799:9 - Variable $a cannot be assigned to as it is passed by reference
$a = $x->value;
ERROR: ImpureByReferenceAssignment - src/BigDecimal.php:800:9 - Variable $b cannot be assigned to as it is passed by reference
$b = $y->value;
...

https://travis-ci.org/brick/math/jobs/648337506

@alexeyshockov Could you please have a look?

`gmp_export` equivalent

Hi,

I am not sure if there is an equivalent method for gmp_export.
In my case, I have a GMP object that I need to export using the following parameters:

$bin = gmp_export($value, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN);

Any idea?

brick/math method for gmp_invert

Hi,

During the implementation of this library in one of my projects, I spent a few moment to find a way to use the GMP method gmp_invert.
In the end, I created my own method, by it could be directly implemented here: the gmp engine will directly use the gmp_invert method. Other engines can use the following.

Hope it helps.

<?php

declare(strict_types=1);

require_once 'vendor/autoload.php';

use Brick\Math\BigInteger;
use Brick\Math\RoundingMode;

function modInverse(BigInteger $a, BigInteger $b): BigInteger
{
    $x = BigInteger::zero();
    $y = BigInteger::zero();
    $g = gcdExtended($a, $b, $x, $y);
    if (!$g->isEqualTo(BigInteger::one())) {
        throw new InvalidArgumentException('Unable to compute the modInverse for the given modulus');
    }

    return $x->mod($b)->plus($b)->mod($b);
}

function gcdExtended(BigInteger $a, BigInteger $b, BigInteger &$x, BigInteger &$y): BigInteger
{
    if ($a->isEqualTo(BigInteger::zero())) {
        $x = BigInteger::zero();
        $y = BigInteger::one();

        return $b;
    }

    $x1 = BigInteger::zero();
    $y1 = BigInteger::zero();
    $gcd = gcdExtended($b->mod($a), $a, $x1, $y1);

    $x = $y1->minus($b->dividedBy($a, RoundingMode::FLOOR)->multipliedBy($x1));
    $y = $x1;

    return $gcd;
}

Example:

gmp_invert(5, 11); //GMP resource of value 9

$five = BigInteger::of(5);
$eleven = BigInteger::of(11);
modInverse($five, $eleven); // BigInteger of value 9

Bitwise NOT

Hi there, first of all, thanks for this great library!

This library has support for bitwise operations and, or and xor, but I found myself needing not. What would be the suggested way of achieving it? Java's BigInteger has a not method. Are we able to have not functionality using any of the existing methods or it would require implementing it?

I know we could do xor with all-1s, or invert the digits of the binary string.

Please advise, thanks!

brick/math method for gmp_random_range

Hi,

Thank you for this library. It solves most of my troubles with GMP and BCMath.
However in one of my projects, I use the method gmp_random_range but haven’t found any replacement here.
Is there an alternative to this method?

Many thanks.
Regards

Support for additional math functions: min, max, sum

It would be convenient to have these methods in library.

BigDecimal::maxOf([1, 0.1, BigDecimal::of('2'), '3']); // BigDecimal::of(3)
BigDecimal::minOf([1, 0.1, BigDecimal::of('2'), '3']); // BigDecimal::of(0.1)
BigDecimal::sumOf([1, 0.1, BigDecimal::of('2'), '3']); // BigDecimal::of(6.1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.