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

BigDecimal's scale should be zero when all fractional digits are zero #81

Closed
aprat84 opened this issue Jul 5, 2024 · 2 comments
Closed

Comments

@aprat84
Copy link

aprat84 commented Jul 5, 2024

When working with databases (MySQL8) and decimal columns, it returns a string with every fractional digit, even when all are zero.

In that case, when all fractional digits are zero, BigDecimal still considers them, and creates an scaled instance:

$a = BigDecimal::of('2');
$b = BigDecimal::of('2.000');

var_dump((string)$a); // '2'
var_dump((string)$b); // '2.000'
var_dump((string)$a === (string)$b); // false

In reality, both are the same exact number, so IMHO they should be represented equally when stringified.

Should the parser consider only significant fractional digits?
I mean, what is the real scale of 2.123000, 3 or 6?

What are your thoughts?


My use case is that I'm testing an XML generation, and printing on it BigDecimals using (string)$value, and it gives different results when using factories than when retrieving entities from DB.

@aprat84 aprat84 changed the title Scale should be zero when all fractional digits are zero BigDecimal's scale should be zero when all fractional digits are zero Jul 5, 2024
@BenMorel
Copy link
Member

BenMorel commented Jul 6, 2024

Hi @aprat84,

In reality, both are the same exact number, so IMHO they should be represented equally when stringified.

I actually think that would make things more confusing. Depending on the application, one can expect BigDecimal to retain the number of decimals you explicitly passed. Java exhibits the same behaviour:

var x = new BigDecimal("123.000000");
System.out.println(x.scale()); // 6
System.out.println(x.toString()); // 123.000000

If you want to compare BigDecimal instances, you should use isEqualTo():

$a = BigDecimal::of('2');
$b = BigDecimal::of('2.000');
$a->isEqualTo($b); // true

If you want to strip trailing zeros, you can use stripTrailingZeros():

$a = BigDecimal::of('123.456000'); // 123.456000
$b = $a->stripTrailingZeros(); // 123.456

You can actually compare string representations of two BigDecimal numbers after applying stripTrailingZeros():

$a = BigDecimal::of('2')->stripTrailingZeros();
$b = BigDecimal::of('2.000')->stripTrailingZeros();

(string) $a === (string) $b; // true

But again, I would strongly recommend to use the built-in comparison methods.

I mean, what is the real scale of 2.123000, 3 or 6?

Maybe related:

@aprat84
Copy link
Author

aprat84 commented Jul 8, 2024

Well, everything you said makes sense, but I don't see why it works like this, though I'm no math expert 😅

Comparing to JAVA BigDecimal, it's equals method also takes into account the scale, so it is not fully equivalent to your isEqualTo method...

As I said, I'm not comparing two instances of BigDecimal, or I would use isEqualTo, but testing generated XML.
I'll use the stripTrailingZeros() method or toScale(...), I'll see.

@aprat84 aprat84 closed this as not planned Won't fix, can't repro, duplicate, stale Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants