Skip to content

BigDecimal treats numerically equal values as different #4863

Description

@lauzadis

aws_smithy_types::BigDecimal stores the original input string and derives PartialEq, Eq, and Hash. As a result, different spellings of the same number compare as different values.

Reproduction

use aws_smithy_types::BigDecimal;
use std::str::FromStr;

#[test]
fn numerically_equal_big_decimals_compare_equal() {
	let scientific = BigDecimal::from_str("1e2").unwrap();
	let plain = BigDecimal::from_str("100").unwrap();

	assert_eq!(scientific, plain);
}

This currently fails because equality compares the stored strings "1e2" and "100" rather than their numeric values.

Other examples include:

  • 1.0 and 1.00
  • +5 and 5
  • -0.0 and 0
  • .5 and 0.5

This was brought up while adding BigDecimal support for CBOR in #4820. CBOR decimal fractions contain an exponent and mantissa, not the original source string. A round trip can change the spelling. CBOR cannot recover every original spelling because values such as +5 and 5 have the same exponent and mantissa.

The underlying issue is not specific to CBOR. Other protocols can also encounter it when a service returns an equivalent number using different formatting.

Expected behavior

Numerically equal BigDecimal values should compare and hash equally, regardless of how they were written.

The implementation should also define whether as_ref() continues to return the original spelling or returns a canonical representation. Preserving the original spelling would be preferred for backwards compatibility with existing serialization behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions