Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for arbitrary-length numbers #10

Open
NhanAZ opened this issue Oct 9, 2022 · 8 comments
Open

Add support for arbitrary-length numbers #10

NhanAZ opened this issue Oct 9, 2022 · 8 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@NhanAZ
Copy link
Contributor

NhanAZ commented Oct 9, 2022

$parser = Parser::createDefault();

$expression = $parser->parse("111111111111111111111111111111111111111111111111111111111111111111111111111");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("111111111111111111111111111111111111111111111");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("99999999999999999999999");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("9999999999999999999999999999999999");
var_dump($expression->evaluate()); // int(9223372036854775807)
@NhanAZ
Copy link
Contributor Author

NhanAZ commented Oct 9, 2022

$parser = Parser::createDefault();

$expression = $parser->parse("--1 + 1");
var_dump($expression->evaluate());
// Expect: int(2)
// Result: Error: Unexpected token encountered at (1:5) "-1+1" when parsing "--1+1"

@Muqsit
Copy link
Owner

Muqsit commented Oct 9, 2022

$parser = Parser::createDefault();

$expression = $parser->parse("111111111111111111111111111111111111111111111111111111111111111111111111111");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("111111111111111111111111111111111111111111111");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("99999999999999999999999");
var_dump($expression->evaluate()); // int(9223372036854775807)

$expression = $parser->parse("9999999999999999999999999999999999");
var_dump($expression->evaluate()); // int(9223372036854775807)

9223372036854775807 resolves to PHP_INT_MAX (on 32-bit computers, this value is 2147483648). Calculators usually throw an "Invalid Input" value when something like this occurs. This could be solved using something such as bcmath but this would make Expression::evaluate() yield a (string) value type and cause an inconsistency in return type based on number range.

$parser = Parser::createDefault();

$expression = $parser->parse("--1 + 1");
var_dump($expression->evaluate());
// Expect: int(2)
// Result: Error: Unexpected token encountered at (1:5) "-1+1" when parsing "--1+1"

--1 + 1 is an invalid expression in PHP and generally in calculators as well, -(-1) + 1 works, -+-1 works as well.

@NhanAZ
Copy link
Contributor Author

NhanAZ commented Oct 9, 2022

i think --1+1 is an invalid expression in PHP but on calculator it's valid...
I tested it on Casio scientific calculators and it works

image

@NhanAZ
Copy link
Contributor Author

NhanAZ commented Oct 9, 2022

For "Invalid Input" I think it should throw an error instead of returning PHP_INT_MAX
(Accurate results should still be preferred instead of throwing an error)

@Muqsit
Copy link
Owner

Muqsit commented Oct 9, 2022

For "Invalid Input" I think it should throw an error instead of returning PHP_INT_MAX (Accurate results should still be preferred instead of throwing an error)

IMO, devs should consider checking for bounds for their application as capping at INT_MIN/MAX is expected behaviour among various programming languages.

@Muqsit
Copy link
Owner

Muqsit commented Oct 9, 2022

One way to support arbitrary-length integers would be by having a separate Parser::createBcMath() that uses bcmath during unary/binary operations, and Parser::createGmp() that uses GMP instead.
But since these extensions return a string or a custom object containing the number:

bcadd(string $num1, string $num2, ?int $scale = null): string
gmp_abs(GMP|int|string $num): GMP

they would interfere with functions such as sin(), cos(), tan(), pow() etc. that accept a number as their input. GMP has a gmp_pow() function but does not have its own functions for trigonometry or many of the other PHP math functions. Each parser (Parser::createDefault(), Parser::createBcMath(), and Parser::createGmp()) would have different sets of available functions.

@Muqsit Muqsit added the enhancement New feature or request label Oct 9, 2022
@Muqsit Muqsit changed the title Results not as expected Add support for arbitrary-length numbers Oct 9, 2022
@Muqsit Muqsit added the help wanted Extra attention is needed label Oct 13, 2022
@NhanAZ
Copy link
Contributor Author

NhanAZ commented Oct 14, 2022

int + int = int

$parser = Parser::createDefault();
$expression = $parser->parse("9223372036854775807 - 1 + 1");
var_dump($expression->evaluate()); // int(9223372036854775807)

same expression but int + int = float

$parser = Parser::createDefault();
$expression = $parser->parse("9223372036854775807 + 1 - 1");
var_dump($expression->evaluate()); // float(9.223372036854776E+18)

@Muqsit
Copy link
Owner

Muqsit commented Oct 14, 2022

int + int = int

$parser = Parser::createDefault();
$expression = $parser->parse("9223372036854775807 - 1 + 1");
var_dump($expression->evaluate()); // int(9223372036854775807)

same expression but int + int = float

$parser = Parser::createDefault();
$expression = $parser->parse("9223372036854775807 + 1 - 1");
var_dump($expression->evaluate()); // float(9.223372036854776E+18)

That is expected behaviour as well according to how PHP performs the operation.
https://3v4l.org/vlom6#v8.1.11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants