Code Monkey home page Code Monkey logo

php-bignumbers's People

Contributors

agungsantoso avatar bitdeli-chef avatar castarco avatar codisart avatar josecelano avatar michaelgooden avatar petrkotek avatar shabbyrobe avatar silentvick avatar stefanmajoor avatar tzhuan 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

php-bignumbers's Issues

Class Decimal not found

  1. Created a composer.json
  2. Grabbed the composer.phar
  3. Composer.phar install and the vendor directory is created
  4. Created a BasicUsage.php one directory level above vendor

php BasicUsage.php prompts Class Decimal not found.

Exponential notation validation

Hello!

The Decimal class throws an exception on numbers like these:

1.048576E+06 // leading zero
3.14E+00     // just zero

But it's a valid form. So I think they should be handled well.

Add formatting method (enhancement)

The default string representation that the Decimal class gives is like this:

(string)Litipk\BigNumbers\Decimal::fromString('11111111111111111.55555555555555')
"11111111111111111.55555555555555"

It would be nice if there is a method to format strings like these to 11,111,111,111,111,111.55555555555555

Add methods in Decimal to allow interaction with PHP's native numbers

In order to allow a more straightforward and efficient interaction with Decimal objects, it would be a great step if we add specific methods to avoid the need of creating new Decimal objects on the fly every time we have to operate with PHP's native numbers.

The current methods (add, mul, div, and so on) have hinting, in order to allow interpreter/compiler optimizations. I propose to create equivalents with the prefix n, for example: mul 's native equivalent will be nMul .

Add BigRational type

We need a type to handle rational numbers with exact precision (Decimal is not enough because it's tailored towards financial and engineering purposes).

It would be useful to fix the issue #22 .

In order to implement BigRational, we'll also need a BigInteger type (#28).

Add `forceAsRational` parameter to the pow method

It would be very useful to determine if we are working with real number approximations or if we explicitly know that we're working with rational numbers when we apply the pow method to a negative number, because the outcome can vary from undefined to a defined value depending on this.

I think fixing #27 before trying to fix the issue will help in this task.

Constructors using self

I am trying to extend Decimal class to add some methods like greaterThan, ...

It would be easier for me if you use self in constructor.

Constructor from integer:

    /**
     * @param  integer $intValue
     * @return Decimal
     */
    public static function fromInteger($intValue)
    {
        ....
        return new Decimal((string)$intValue, 0);
    }

Extended class example:

class ExtrendedDecimal
{
    /**
     * @param  Decimal $b
     * @param  integer $scale
     * @return bool
     */
    public function greaterThan(Decimal $b, $scale = null)
    {
        if ($this->comp($b, $scale) == 1)
            return true;
        else
            return false;
    }
}

New using Self:

return new Self((string)$intValue, 0);

I know that is not a great new feature but I want to use my own class in case I need some extensions in the future.

Leading decimal not supported in fromString

When creating from a string value leading decimals cause a NaNInputError.

// Works
\Litipk\BigNumbers\Decimal::fromString('0.110');

// PHP Fatal error:  Uncaught Litipk\BigNumbers\Errors\NaNInputError: strValue must be a number
\Litipk\BigNumbers\Decimal::fromString('.110');

A simple fix would be adding the following to fromString()

if (substr($strValue, 0, 1) === '.') {
    $strValue = '0' . $strValue;
}

New release version

There have been numerous improvements since the 0.7.2 release - is it possible to get a new release version tagged and added to packagist?

Improve the coverage metrics by improving* tests

Test annotations

Currently, the unit tests of the library aren't properly marked with the @uses and @covers annotations to indicate what's the test intending to cover. This fact leads us to an optimistic and erroneous code coverage ratio, potentially hiding important bugs.

Using Mutation testing, at least locally

Mutation testing it's very useful to discover new bugs and discover test coverage "holes". Recently has appeared a new PHP mutation testing called Humbug, which could be used to improve the library's tests.

I've been experimenting without success (I didn't spent enough time, and the project is currently in alpha or beta state), but if anyone wants to experiment, I think the task is worth.

  • Tests annotations
  • Mutation testing

abs method doesnt work with long negative numbers.

got this value -2.689785E + 23 and i need convert it to absolute before work with him.

When abs method is used, it returns 0. I was checking why and it's about that abs checks if number is zero before call additiveInverse, that method also check if value is zero.

The scale with that number is -1 automaticaly, then the check of isZero always returns true.

Add trigonometric functions

It would be nice to have the following trigonometric functions:

  • sin : sine
  • cos : cosine
  • tan : tangent
  • cotan : cotangent
  • sec : secant
  • cosec : cosecant
  • arcsin : arcsine
  • arccos : arccosine
  • arctan : arctangent
  • arccot : arccotangent
  • arcsec : arcsecant
  • arccsc : arccosecant

Float precision errors using number_format()

When using number_format() like here, you are relying on php's float precision.

Trying to use a number like Decimal::fromFloat(90.05) will cause a precision error as number_format(90.05, 16, ".", "") === "90.0499999999999972".

There needs to be another method used to load in the numbers initially, as all following operation are going to be wrong.

Bug with the innerRound method with negative Decimal

I was testing negative values for tangent and cotangente when i found several rounding errors.

I followed the process and I think there is a mistake with the rounding of negative numbers.

Exemple : I use the division of 0.984376 by -0.176077. the result is -5.59059956723478932512..

but with the Decimal::div(), it gives
for the scale of 3 : -5.589
for the scale of 4 : -5.5904
for the scale of 5 : -5.59058
for the scale of 6 : -5.590598

I think i have pinpointed the probleme in Decimal::innerRound().
When a number is negative and if the next digit after the scale is greater than 5, the one should be substracted and not added.

Transfer the project ownership to an organization

Hi,

I'm thinking about creating an organization to hold scientific and mathematical libraries projects in PHP, and sharing the ownership of this organization with more people to improve the reliability of projects like this one.

I have three other projects which I would transfer to this hypothetical organization:

  • https://github.com/Litipk/Jupyter-PHP
  • https://github.com/Litipk/php-timeseries - this one is also paused... because I want to transform it to be a PECL extension with native PHP polyfills for the people who cannot afford installing not official extensions.
  • And my "dead" project PHP-MagicTheorist (I hope I'll find time someday to give it the work it deserves). But don't worry, I won't transfer it until I improve it enough to make it usable, I don't want to waste the time of the other people with junk code.

@codisart , I'm mentioning you because maybe you're interested. I hope you don't get this mention as SPAM ^_^U .

`mod()` fails for values >= .95 && < 1.0.

When I run the DecimalModTest::testFiniteFiniteMod() test using the following data sets, I get failures:

Data Provider

            # Extant passing tests.
            ['10', '3', '1'],
            ['34', '3.4', '0'],
            ['15.1615', '3.156156', '2.536876'],
            ['15.1615', '3.156156', '2.5369', 4],
            ['-3.4', '-2', '-1.4'],
            ['3.4', '-2', '-0.6'],
            ['-3.4', '2', '0.6'],

            # New tests.
            ['0.949', '1', '0.949'],
            ['0.95', '1', '0.95'],
            ['0.99', '1', '0.99'],
            ['1', '1', '0'],

Test Results

PHPUnit 6.5.14 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.10-1+ubuntu18.04.1+deb.sury.org+1
Configuration: /home/vagrant/www/php-bignumbers/phpunit.xml
Error:         No code coverage driver is available

........FF.                                                       11 / 11 (100%)

Time: 338 ms, Memory: 6.00MB

There were 2 failures:

1) DecimalModTest::testFiniteFiniteMod with data set #8 ('0.95', '1', '0.95')
-0.05 % 1 must be equal to 0.95, but was -0.05
Failed asserting that false is true.

/home/vagrant/www/php-bignumbers/tests/Decimal/DecimalModTest.php:37

2) DecimalModTest::testFiniteFiniteMod with data set #9 ('0.99', '1', '0.99')
-0.01 % 1 must be equal to 0.99, but was -0.01
Failed asserting that false is true.

/home/vagrant/www/php-bignumbers/tests/Decimal/DecimalModTest.php:37

However, when I run the 2 failing tests through PHP's native fmod(), I get expected results:

php > echo fmod(.95, 1);
0.95
php > echo fmod(.99, 1);
0.99
php > 

Add `BigInteger` type

Decimalisn't enough to handle integer properties because the following reasons:

  • Integer needs encapsulating integer-specific algorithms (like maximum common divisor, or primes factorization).
  • We can't continue adding code to Decimal because it's too complex now.
  • Decimal is slow because we can't use GMP. On the other hand, using GMP with Integers is a good idea.
  • We need a BigInteger type to implement the BigRational type (#27).

Add BigFloat type

Related to bug #8 . In order to allow really big numbers (with very large exponents), Decimal isn't enough, so we need to introduce a float point type.

PHP's float/double type also allows very large numbers, but exponents limits vary from 256 values to 16536 values depending on the CPU, with a BigFloat type we can work with very large exponents. This type will be slower than native the native float type, but the tradeoff is worth. The explanation about exponents it's also applicable to mantissas.

It's important to implement conversion methods 'from & to' Decimal objects in the numeric range where it's possible.

It would be nice if we implement in the Decimal type a system to detect when it's preferable to switch to BigFloat. Maybe capturing memory exhaustion exceptions and handling it?

Division by zero warning in innerLog10

Two previous tickets have resolved other division by zero issues in the innerLog10 method, however we've encountered another when dealing with Decimals created from floats when the precision is being calculated to a higher value than the 'length'. This results in a negative $value_log10_approx which triggers a division by zero warning in \bcdiv:

image

To replicate:

$x = Decimal::fromFloat(1.001);
// PHP Warning:  bcdiv(): Division by zero in /vendor/litipk/php-bignumbers/src/Decimal.php on line 1159
$x->div(Decimal::fromFloat(1.0));

Add BigComplex type

Complex numbers are very interesting because they have a lot of uses in scientific and engineering computations. They are a MUST in a good numeric computation library.

This new feature must be carefully designed because ideally it have to use the other numeric types internally to reuse code and obtain a clean class. The problem is that we have Decimal, but also we're planning to add BigRational and BigInteger.

Maybe we can't discard using BigInteger, but the first two options should be an option to represent the complex number components, so we need a very flexible class.

Critical: huge calculation error on integer numbers with the type "float"

What is going on here? I couldn't understand what this line (and the concept of "natural scale") is for:

https://github.com/Litipk/php-bignumbers/blob/master/src/Decimal.php#L102

When you have a scale set, it wrongly adds zeroes for some reason:

define('PRECISION', 8);
print Decimal::create(4, PRECISION)->asFloat(); // prints "4";
print Decimal::create(4.0, PRECISION)->asFloat(); // prints "400000000";
print Decimal::create((float)4, PRECISION)->asFloat(); // prints "400000000";

Was your goal to arrive at "4.00000000" instead?

[WIP] The documentation is outdated

The documentation is outdated, it refers to NaN objects, but those objects where removed from php-bignumbers in favour of throwing exceptions in order to make easier to ensure code correctness.

In addition, it's preferable to move the documentation to another file or to the project's wiki, the README.md file should be for more general information.

Add `isInteger` method to Decimal

It's very useful to check if a number is an integer number in order to properly handle cases where we apply pow on negative numbers.

Bring back php-exceptions

Please bring back php-exceptions repository. We're still using php5, so that means we use 0.7.3 version which has a dependancy on php-exceptions.

ceil function returns float

It affects Decimals with auto-calculated scales.

For example:

print Decimal::create(10.13777777)->div(Decimal::create(1));

bcdiv() division by zero error

When running the following code, I get a PHP division by zero warning: PHP Warning: bcdiv(): Division by zero in vendor/litipk/php-bignumbers/src/Decimal.php on line 1140

<?php
declare(strict_types=1);
require("vendor/autoload.php");
use Litipk\BigNumbers\Decimal;

$d1 = Decimal::create(192078120.5, 28);
$d2 = Decimal::create(31449600, 28);

echo $d1->div($d2);

If I remove the .5 from the first value, the division by zero warning does not occur. Similarly, if I pass 28 as the second parameter to div(), the warning does not occur.

I'm using v0.8.2 of this package, running on PHP 7.1.2 (cli) with opcache enabled. Xdebug is not installed. Please don't hesitate to request more information.

Division by zero error in div()

When using the library for divisions at a higher scale, you can run into division by zero errors:

<?php

declare(strict_types=1);

use Litipk\BigNumbers\Decimal;

require_once __DIR__ . '/vendor/autoload.php';

$value = Decimal::create('12.99', 4);
$divisor = Decimal::create(2, 4);

var_dump($value->div($divisor));
Warning: bcdiv(): Division by zero in src/Decimal.php on line 1155

The affected part is the innerLog10 method used while calculating the division.

[WIP] Add important numerical constants

A list of important numerical constants.

Interfaces

  • Zero
  • One
  • PI
  • E
  • Euler - Mascheroni Constant
  • Golden Ratio
  • Silver Ratio
  • Light Speed

Arbitrary precision (via $scale parameter)

  • PI
  • E
  • Euler - Mascheroni Constant
  • Golden Ratio
  • Silver Ratio

Integration with Decimal

  • Use the Zero constant instead of creating new zero objects inside Decimal methods.
  • Use the One constant instead of creating new one objects inside Decimal methods.

The non-phisical numerical constants must be associated to a method with the following signature:

public static function ConstantName($scale);

This methods will allow to specify how many digits we want for every one of the supported numerical constants.

The Big Refactor (formerly "Add BigReal interface")

EDIT : This idea is no longer proposed, a new issue will be posted if we arrive to a consensus in this thread.

Because we want to introduce new classes for big numbers (See #15, #27, #28 and #29), it would be necessary to create a BigRealinterface or abstract class (more probably the second one) in order to allow interoperability between those classes.

Currently, the class Decimal have many defined methods, but almost all the methods use the$scale`parameter, which is very specific for this type. Because it's desirable to use type hinting in the methods signatures, and because PHP doesn't allow classical method overliading (as in Java or C#), I propose to do a big refactor with the following steps:

  • rename the shareable methods from "method" to "dMethod" in the Decimal class (de ''d'' is for Decimal), where method refers to the previous method name, for example mul or add.
  • Add new methods with the old names, but without the $scaleparameter, and hinting the BigNumbertype instead of Decimal. Those methods should have a switch-like control structure to map the calls to the specific-type methods :
    • dMethod for Decimal
    • rMethod for BigRational
    • iMethodfor BigInteger
    • cMethodfor BigComplex
    • nMethod for PHP's native types (see #16).
  • Extract the new created methods to the new BigRealabstract class, and make Decimalto inherit from BigReal.

Important Note: I'm talking about BigRealand not about BigNumber because this way we have more flexibility . Number is a very general concept, and may be in the future we want to implement other number types (not only real or complex numbers, but... say finite fields, quaternions or whatever you can imagine).

Unexpected rounding results

The round method does not yield expected results. To reproduce:

$oneHundred = Decimal::fromInteger(100);
$grossAmount = Decimal::create(6.45);
$netAmount = $grossAmount->mul($oneHundred->div($oneHundred->add(Decimal::fromInteger(19))));
$vat = $grossAmount->sub($netAmount);
var_dump($vat->innerValue());
var_dump($vat->round(3)->innerValue());

(so basically, grossAmount - grossAmount / 1.19)

The second dump should display 1.03 but displays 1.032. Other inputs for $grossAmount which lead to rounding error are:

  • 29.95 results in 4.792 while 4.782 is expected.
  • 12.26 results in 1.962 while 1.958 is expected.

For comparison, I have performed the same calculations using a desktop calculator, GNOME calculator and https://www.geogebra.org/calculator, all of which yield the expected results.

(I have used float as input for $grossAmount because an external interface gives me a float, over which I have no control. Even with string as input, the rounding is unexpected.)

Incorrect decimal calculation.

Using PHP 7.3.6 I get the following results using PHP "straight math":

php > echo 156 + (44 / 60) + (31 / 3600);
156.74194444444

Using this library (same system and PHP version), I get:

156.7386

On my iPhone and Mac, I get the same value as this library. However, on a Microsoft Surface Go tablet, Google's online calculator and an Android phone, I get:

156.741944444

Google's Calculator
https://www.google.com/search?q=online+calculator

Add round up

Right now, rounding a decimal will only round half up, I need a round up (ceiling). Looking through the code it seems that just changing the >= 5 to > 0 will make this happen.

Long exponential part causes an error

I noticed that there is no size check of exponential part. If I pass something like this:

1.33E+3333333333333333333333

It will cause "Allowed memory size exhausted" error.

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.