Skip to content

Commit 60d278b

Browse files
committed
feat: add division configuration system with strategies and precision scales
1 parent f5e3f29 commit 60d278b

File tree

7 files changed

+536
-52
lines changed

7 files changed

+536
-52
lines changed

CHANGELOG.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
## [0.0.17] - 2025-01-XX
11+
12+
### Added
13+
- **Division Configuration System**: New helper objects to make division operations more intuitive and type-safe
14+
- `PrecisionScale` object with constants for common decimal place requirements:
15+
- `CURRENCY` (2 decimals) - for money calculations
16+
- `EXCHANGE_RATE` (4 decimals) - for forex/currency conversion
17+
- `PERCENTAGE` (2 decimals) - for percentage calculations
18+
- `SCIENTIFIC` (10 decimals) - for scientific computations
19+
- `HIGH_PRECISION` (20 decimals) - for very precise calculations
20+
- `INTEREST_RATE` (6 decimals) - for interest rate calculations
21+
- `CRYPTOCURRENCY` (8 decimals) - for Bitcoin and crypto calculations
22+
- `DivisionConfig` data class that combines scale and rounding mode
23+
- `DivisionStrategy` object with predefined division strategies:
24+
- `CURRENCY` - 2 decimals with HALF_UP rounding
25+
- `FINANCIAL` - 2 decimals with HALF_EVEN (banker's) rounding
26+
- `EXCHANGE_RATE` - 4 decimals with HALF_UP rounding
27+
- `PERCENTAGE` - 2 decimals with HALF_UP rounding
28+
- `SCIENTIFIC` - 10 decimals with HALF_UP rounding
29+
- `HIGH_PRECISION` - 20 decimals with HALF_UP rounding
30+
- `INTEREST_RATE` - 6 decimals with HALF_UP rounding
31+
- `CRYPTOCURRENCY` - 8 decimals with HALF_UP rounding
32+
- `EXACT` - requires exact result or throws ArithmeticException
33+
- New `divide(other: KBigDecimal, config: DivisionConfig)` overload for cleaner division syntax
34+
35+
### Changed
36+
- **Improved Division API**: Clients can now use predefined strategies instead of manually specifying scale and rounding mode
37+
38+
### Example Usage
39+
```kotlin
40+
// Before
41+
val result = price.divide(quantity, 2, RoundingMode.HALF_UP)
42+
43+
// After - using strategy
44+
val result = price.divide(quantity, DivisionStrategy.CURRENCY)
45+
46+
// After - using custom config
47+
val result = price.divide(quantity, DivisionConfig(scale = 4, roundingMode = RoundingMode.HALF_EVEN))
48+
49+
// Using scale constants
50+
val result = price.divide(quantity, PrecisionScale.CRYPTOCURRENCY, RoundingMode.HALF_UP)
51+
```
52+
53+
## [0.0.16] - 2025-01-XX
54+
55+
### Fixed
56+
- Enhanced KBigDecimal division for precision and special cases
57+
- Added single-parameter divide function with automatic scale determination
58+
59+
### Changed
60+
- Updated documentation to include new single-parameter divide function
61+
62+
## [0.0.1] - Initial Release
63+
64+
### Added
65+
- `KBigDecimal` interface for arbitrary precision decimal arithmetic
66+
- `KBigInteger` interface for arbitrary precision integer arithmetic
67+
- `KBigMath` utility class for advanced mathematical operations
68+
- Operator overloading support for natural mathematical syntax
69+
- Extension functions for easy type conversion
70+
- Factory methods for creating big numbers from various types
71+
- Comprehensive test coverage
72+
- Android and iOS platform support
73+
- Support for basic arithmetic operations (add, subtract, multiply, divide)
74+
- Support for advanced operations (sqrt, factorial, gcd, lcm, isPrime, pow)
75+
- Rounding mode support for decimal operations
76+
- Platform-optimized implementations using native libraries
77+
78+
[Unreleased]: https://github.com/gatrongdev/kbignum/compare/v0.0.17...HEAD
79+
[0.0.17]: https://github.com/gatrongdev/kbignum/compare/v0.0.16...v0.0.17
80+
[0.0.16]: https://github.com/gatrongdev/kbignum/releases/tag/v0.0.16
81+
[0.0.1]: https://github.com/gatrongdev/kbignum/releases/tag/v0.0.1

README.md

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Add to your `build.gradle.kts`:
2727

2828
```kotlin
2929
dependencies {
30-
implementation("io.github.gatrongdev:kbignum:0.0.1")
30+
implementation("io.github.gatrongdev:kbignum:0.0.17")
3131
}
3232
```
3333

@@ -37,7 +37,7 @@ Add to your `build.gradle`:
3737

3838
```gradle
3939
dependencies {
40-
implementation 'io.github.gatrongdev:kbignum:0.0.1'
40+
implementation 'io.github.gatrongdev:kbignum:0.0.17'
4141
}
4242
```
4343

@@ -57,8 +57,16 @@ val bigInteger = "12345678901234567890".toKBigInteger()
5757
val sum = bigDecimal1 + bigDecimal2
5858
val difference = bigDecimal1 - bigDecimal2
5959
val product = bigDecimal1 * bigDecimal2
60-
val quotient = bigDecimal1.divide(bigDecimal2, 10) // 10 decimal places
61-
val simpleQuotient = bigDecimal1.divide(bigDecimal2) // uses automatic scale
60+
61+
// Division with automatic scale
62+
val simpleQuotient = bigDecimal1.divide(bigDecimal2)
63+
64+
// Division with predefined strategies (v0.0.17+)
65+
val currencyResult = bigDecimal1.divide(bigDecimal2, DivisionStrategy.CURRENCY)
66+
val preciseResult = bigDecimal1.divide(bigDecimal2, DivisionStrategy.SCIENTIFIC)
67+
68+
// Division with custom configuration
69+
val customResult = bigDecimal1.divide(bigDecimal2, DivisionConfig(scale = 10, roundingMode = RoundingMode.HALF_UP))
6270

6371
// Advanced operations
6472
val sqrt = KBigMath.sqrt(bigDecimal1, 10)
@@ -92,6 +100,18 @@ val power = KBigMath.pow(bigDecimal1, 5)
92100
// Precision control
93101
val scaled = bigDecimal1.setScale(5, RoundingMode.HALF_UP)
94102
val precision = bigDecimal1.precision()
103+
104+
// Division strategies (v0.0.17+)
105+
val price = "100.00".toKBigDecimal()
106+
val quantity = "3".toKBigDecimal()
107+
108+
// Use predefined strategies
109+
val pricePerItem = price.divide(quantity, DivisionStrategy.CURRENCY) // 33.33
110+
val exchangeRate = price.divide(quantity, DivisionStrategy.EXCHANGE_RATE) // 33.3333
111+
val cryptoAmount = price.divide(quantity, DivisionStrategy.CRYPTOCURRENCY) // 33.33333333
112+
113+
// Use precision scale constants
114+
val interestRate = price.divide(quantity, PrecisionScale.INTEREST_RATE, RoundingMode.HALF_UP)
95115
```
96116

97117
## API Reference
@@ -105,10 +125,27 @@ Interface for arbitrary precision decimal numbers:
105125
- `multiply(other: KBigDecimal): KBigDecimal`
106126
- `divide(other: KBigDecimal): KBigDecimal`
107127
- `divide(other: KBigDecimal, scale: Int): KBigDecimal`
128+
- `divide(other: KBigDecimal, scale: Int, mode: Int): KBigDecimal`
129+
- `divide(other: KBigDecimal, config: DivisionConfig): KBigDecimal` *(v0.0.17+)*
108130
- `abs(): KBigDecimal`
109131
- `signum(): Int`
110132
- `setScale(scale: Int, roundingMode: Int): KBigDecimal`
111133

134+
### Division Helpers (v0.0.17+)
135+
136+
**PrecisionScale** - Constants for common decimal places:
137+
- `CURRENCY` (2), `EXCHANGE_RATE` (4), `PERCENTAGE` (2)
138+
- `SCIENTIFIC` (10), `HIGH_PRECISION` (20), `INTEREST_RATE` (6)
139+
- `CRYPTOCURRENCY` (8)
140+
141+
**DivisionStrategy** - Predefined strategies:
142+
- `CURRENCY`, `FINANCIAL`, `EXCHANGE_RATE`, `PERCENTAGE`
143+
- `SCIENTIFIC`, `HIGH_PRECISION`, `INTEREST_RATE`
144+
- `CRYPTOCURRENCY`, `EXACT`
145+
146+
**DivisionConfig** - Custom configuration:
147+
- `DivisionConfig(scale: Int, roundingMode: Int = RoundingMode.HALF_UP)`
148+
112149
### KBigInteger
113150

114151
Interface for arbitrary precision integers:

shared/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ plugins {
1717
}
1818

1919
group = "io.github.gatrongdev"
20-
version = "0.0.16"
20+
version = "0.0.17"
2121

2222
kotlin {
2323
androidTarget {

shared/src/commonMain/kotlin/io/github/gatrongdev/kbignum/math/KBigDecimal.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,34 @@ interface KBigDecimal : Comparable<KBigDecimal> {
6060
mode: Int,
6161
): KBigDecimal
6262

63+
/**
64+
* Returns a KBigDecimal that is the quotient of this divided by the specified value using a division configuration.
65+
* This is a convenient method that accepts a DivisionConfig or DivisionStrategy preset.
66+
*
67+
* @param other The divisor
68+
* @param config The division configuration specifying scale and rounding mode
69+
* @return The result of the division with the configured scale and rounding mode
70+
* @throws ArithmeticException if other is zero or if rounding is necessary but the rounding mode is UNNECESSARY
71+
*
72+
* Example usage:
73+
* ```
74+
* val price = "100.00".toKBigDecimal()
75+
* val quantity = "3".toKBigDecimal()
76+
*
77+
* // Using predefined strategy
78+
* val pricePerItem = price.divide(quantity, DivisionStrategy.CURRENCY)
79+
* // Result: 33.33
80+
*
81+
* // Using custom config
82+
* val result = price.divide(quantity, DivisionConfig(scale = 4, roundingMode = RoundingMode.HALF_EVEN))
83+
* // Result: 33.3333
84+
* ```
85+
*/
86+
fun divide(
87+
other: KBigDecimal,
88+
config: DivisionConfig,
89+
): KBigDecimal = divide(other, config.scale, config.roundingMode)
90+
6391
/**
6492
* Returns the absolute value of this KBigDecimal.
6593
* @return The absolute value (always non-negative)

shared/src/commonMain/kotlin/io/github/gatrongdev/kbignum/math/KBigNumberFactory.kt

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,145 @@ object RoundingMode {
117117
/** Rounding mode to assert that the requested operation has an exact result */
118118
const val UNNECESSARY = 7
119119
}
120+
121+
/**
122+
* Precision scale constants for common use cases.
123+
* These constants define standard decimal places for various types of calculations.
124+
*/
125+
object PrecisionScale {
126+
/** Scale for currency calculations (2 decimal places) - e.g., $10.99 */
127+
const val CURRENCY = 2
128+
129+
/** Scale for exchange rates (4 decimal places) - e.g., 1.2345 USD/EUR */
130+
const val EXCHANGE_RATE = 4
131+
132+
/** Scale for percentage calculations (2 decimal places) - e.g., 12.34% */
133+
const val PERCENTAGE = 2
134+
135+
/** Scale for high precision scientific calculations (10 decimal places) */
136+
const val SCIENTIFIC = 10
137+
138+
/** Scale for very high precision calculations (20 decimal places) */
139+
const val HIGH_PRECISION = 20
140+
141+
/** Scale for interest rate calculations (6 decimal places) */
142+
const val INTEREST_RATE = 6
143+
144+
/** Scale for cryptocurrency calculations (8 decimal places) - e.g., BTC */
145+
const val CRYPTOCURRENCY = 8
146+
}
147+
148+
/**
149+
* Configuration for division operations combining scale and rounding mode.
150+
* @property scale Number of digits to the right of the decimal point
151+
* @property roundingMode Rounding mode to apply (see RoundingMode constants)
152+
*/
153+
data class DivisionConfig(
154+
val scale: Int,
155+
val roundingMode: Int = RoundingMode.HALF_UP,
156+
)
157+
158+
/**
159+
* Predefined division strategies for common use cases.
160+
* Each strategy combines a scale and rounding mode optimized for specific scenarios.
161+
*/
162+
object DivisionStrategy {
163+
/**
164+
* Currency division (2 decimal places, HALF_UP rounding).
165+
* Suitable for: money calculations, prices, financial transactions.
166+
* Example: $100 / 3 = $33.33
167+
*/
168+
val CURRENCY =
169+
DivisionConfig(
170+
scale = PrecisionScale.CURRENCY,
171+
roundingMode = RoundingMode.HALF_UP,
172+
)
173+
174+
/**
175+
* Financial division (2 decimal places, HALF_EVEN rounding).
176+
* Suitable for: accounting, banking (banker's rounding for fairness).
177+
* Example: reduces cumulative rounding bias in repeated calculations
178+
*/
179+
val FINANCIAL =
180+
DivisionConfig(
181+
scale = PrecisionScale.CURRENCY,
182+
roundingMode = RoundingMode.HALF_EVEN,
183+
)
184+
185+
/**
186+
* Exchange rate division (4 decimal places, HALF_UP rounding).
187+
* Suitable for: currency conversion, forex calculations.
188+
* Example: 100 USD / 1.2345 = 81.0037 EUR
189+
*/
190+
val EXCHANGE_RATE =
191+
DivisionConfig(
192+
scale = PrecisionScale.EXCHANGE_RATE,
193+
roundingMode = RoundingMode.HALF_UP,
194+
)
195+
196+
/**
197+
* Percentage division (2 decimal places, HALF_UP rounding).
198+
* Suitable for: percentage calculations, ratios.
199+
* Example: 50 / 3 = 16.67%
200+
*/
201+
val PERCENTAGE =
202+
DivisionConfig(
203+
scale = PrecisionScale.PERCENTAGE,
204+
roundingMode = RoundingMode.HALF_UP,
205+
)
206+
207+
/**
208+
* Scientific division (10 decimal places, HALF_UP rounding).
209+
* Suitable for: scientific computations, engineering calculations.
210+
* Example: high precision results for research
211+
*/
212+
val SCIENTIFIC =
213+
DivisionConfig(
214+
scale = PrecisionScale.SCIENTIFIC,
215+
roundingMode = RoundingMode.HALF_UP,
216+
)
217+
218+
/**
219+
* High precision division (20 decimal places, HALF_UP rounding).
220+
* Suitable for: very precise calculations requiring minimal rounding error.
221+
* Example: complex mathematical computations
222+
*/
223+
val HIGH_PRECISION =
224+
DivisionConfig(
225+
scale = PrecisionScale.HIGH_PRECISION,
226+
roundingMode = RoundingMode.HALF_UP,
227+
)
228+
229+
/**
230+
* Interest rate division (6 decimal places, HALF_UP rounding).
231+
* Suitable for: interest calculations, APR/APY computations.
232+
* Example: 5% / 12 months = 0.416667% per month
233+
*/
234+
val INTEREST_RATE =
235+
DivisionConfig(
236+
scale = PrecisionScale.INTEREST_RATE,
237+
roundingMode = RoundingMode.HALF_UP,
238+
)
239+
240+
/**
241+
* Cryptocurrency division (8 decimal places, HALF_UP rounding).
242+
* Suitable for: Bitcoin and other crypto calculations.
243+
* Example: 1 BTC / 3 = 0.33333333 BTC
244+
*/
245+
val CRYPTOCURRENCY =
246+
DivisionConfig(
247+
scale = PrecisionScale.CRYPTOCURRENCY,
248+
roundingMode = RoundingMode.HALF_UP,
249+
)
250+
251+
/**
252+
* Exact division (requires exact result, no rounding).
253+
* Suitable for: divisions that must be exact or throw exception.
254+
* Example: 10 / 2 = 5 (exact), but 10 / 3 throws ArithmeticException
255+
*/
256+
val EXACT =
257+
DivisionConfig(
258+
scale = 0,
259+
roundingMode = RoundingMode.UNNECESSARY,
260+
)
261+
}

0 commit comments

Comments
 (0)