0
# Math Utilities
1
2
Apache Commons Lang provides robust mathematical utilities through NumberUtils, Range classes, and Fraction operations. These utilities offer safe number parsing, validation, comparison, and range operations that handle edge cases and null values gracefully.
3
4
## Core Classes
5
6
### NumberUtils - Number Parsing and Validation
7
8
Provides 82 static methods for safe number operations, parsing, and validation:
9
10
```java { .api }
11
import org.apache.commons.lang3.math.NumberUtils;
12
```
13
14
#### Number Constants
15
16
```java { .api }
17
// Wrapper type constants for common values
18
public static final Long LONG_ZERO = Long.valueOf(0L)
19
public static final Long LONG_ONE = Long.valueOf(1L)
20
public static final Long LONG_MINUS_ONE = Long.valueOf(-1L)
21
public static final Integer INTEGER_ZERO = Integer.valueOf(0)
22
public static final Integer INTEGER_ONE = Integer.valueOf(1)
23
public static final Integer INTEGER_TWO = Integer.valueOf(2)
24
public static final Integer INTEGER_MINUS_ONE = Integer.valueOf(-1)
25
public static final Short SHORT_ZERO = Short.valueOf((short) 0)
26
public static final Short SHORT_ONE = Short.valueOf((short) 1)
27
public static final Short SHORT_MINUS_ONE = Short.valueOf((short) -1)
28
public static final Byte BYTE_ZERO = Byte.valueOf((byte) 0)
29
public static final Byte BYTE_ONE = Byte.valueOf((byte) 1)
30
public static final Byte BYTE_MINUS_ONE = Byte.valueOf((byte) -1)
31
public static final Double DOUBLE_ZERO = Double.valueOf(0.0d)
32
public static final Double DOUBLE_ONE = Double.valueOf(1.0d)
33
public static final Double DOUBLE_MINUS_ONE = Double.valueOf(-1.0d)
34
public static final Float FLOAT_ZERO = Float.valueOf(0.0f)
35
public static final Float FLOAT_ONE = Float.valueOf(1.0f)
36
public static final Float FLOAT_MINUS_ONE = Float.valueOf(-1.0f)
37
```
38
39
**Usage Examples:**
40
```java { .api }
41
// Using predefined constants to avoid object creation
42
Integer zero = NumberUtils.INTEGER_ZERO; // Better than Integer.valueOf(0)
43
Long one = NumberUtils.LONG_ONE; // Better than Long.valueOf(1L)
44
Double minusOne = NumberUtils.DOUBLE_MINUS_ONE; // Better than Double.valueOf(-1.0d)
45
```
46
47
#### Safe Number Parsing
48
49
```java { .api }
50
// Integer parsing with defaults
51
public static int toInt(String str)
52
public static int toInt(String str, int defaultValue)
53
54
// Long parsing with defaults
55
public static long toLong(String str)
56
public static long toLong(String str, long defaultValue)
57
58
// Float parsing with defaults
59
public static float toFloat(String str)
60
public static float toFloat(String str, float defaultValue)
61
62
// Double parsing with defaults
63
public static double toDouble(String str)
64
public static double toDouble(String str, double defaultValue)
65
66
// Byte parsing with defaults
67
public static byte toByte(String str)
68
public static byte toByte(String str, byte defaultValue)
69
70
// Short parsing with defaults
71
public static short toShort(String str)
72
public static short toShort(String str, short defaultValue)
73
```
74
75
**Usage Examples:**
76
```java { .api }
77
// Safe parsing without exceptions
78
int number1 = NumberUtils.toInt("123"); // 123
79
int number2 = NumberUtils.toInt("invalid"); // 0 (default)
80
int number3 = NumberUtils.toInt("invalid", -1); // -1 (custom default)
81
int number4 = NumberUtils.toInt(null, 100); // 100
82
83
// Parsing different number types
84
long longValue = NumberUtils.toLong("999999999999"); // 999999999999L
85
double doubleValue = NumberUtils.toDouble("3.14"); // 3.14
86
float floatValue = NumberUtils.toFloat("2.5f"); // 2.5f
87
byte byteValue = NumberUtils.toByte("127"); // 127
88
short shortValue = NumberUtils.toShort("1000"); // 1000
89
90
// Handling edge cases
91
double nan = NumberUtils.toDouble("NaN"); // NaN
92
double infinity = NumberUtils.toDouble("Infinity"); // Infinity
93
```
94
95
#### Advanced Number Parsing
96
97
```java { .api }
98
// Create Number objects from strings
99
public static Number createNumber(String str) throws NumberFormatException
100
public static BigInteger createBigInteger(String str)
101
public static BigDecimal createBigDecimal(String str)
102
103
// Parse with specific radix
104
public static int toInt(String str, int defaultValue, int radix)
105
public static long toLong(String str, long defaultValue, int radix)
106
```
107
108
**Usage Examples:**
109
```java { .api }
110
// Automatic number type detection
111
Number num1 = NumberUtils.createNumber("123"); // Integer
112
Number num2 = NumberUtils.createNumber("123L"); // Long
113
Number num3 = NumberUtils.createNumber("123.45"); // Double
114
Number num4 = NumberUtils.createNumber("123.45f"); // Float
115
Number num5 = NumberUtils.createNumber("123.45d"); // Double
116
117
// Big number creation
118
BigInteger bigInt = NumberUtils.createBigInteger("12345678901234567890");
119
BigDecimal bigDec = NumberUtils.createBigDecimal("123.456789012345678901234");
120
121
// Parsing with different radix
122
int hex = NumberUtils.toInt("FF", 0, 16); // 255
123
int binary = NumberUtils.toInt("1010", 0, 2); // 10
124
int octal = NumberUtils.toInt("17", 0, 8); // 15
125
```
126
127
#### Number Validation
128
129
```java { .api }
130
// Check if string represents a number
131
public static boolean isCreatable(String str)
132
public static boolean isParsable(String str)
133
134
// Specific type validation
135
public static boolean isDigits(String str)
136
```
137
138
**Usage Examples:**
139
```java { .api }
140
// Number format validation
141
boolean isNum1 = NumberUtils.isCreatable("123"); // true
142
boolean isNum2 = NumberUtils.isCreatable("123.45"); // true
143
boolean isNum3 = NumberUtils.isCreatable("123L"); // true
144
boolean isNum4 = NumberUtils.isCreatable("invalid"); // false
145
boolean isNum5 = NumberUtils.isCreatable(null); // false
146
147
// Parsable validation (stricter)
148
boolean parsable1 = NumberUtils.isParsable("123"); // true
149
boolean parsable2 = NumberUtils.isParsable("123L"); // false (L suffix not parsable)
150
boolean parsable3 = NumberUtils.isParsable("123.0"); // true
151
152
// Digits only validation
153
boolean digits1 = NumberUtils.isDigits("123"); // true
154
boolean digits2 = NumberUtils.isDigits("123.45"); // false (contains decimal)
155
boolean digits3 = NumberUtils.isDigits("-123"); // false (contains minus sign)
156
```
157
158
#### Min/Max Operations
159
160
```java { .api }
161
// Min operations for all numeric types
162
public static byte min(byte... array)
163
public static double min(double... array)
164
public static float min(float... array)
165
public static int min(int... array)
166
public static long min(long... array)
167
public static short min(short... array)
168
169
// Max operations for all numeric types
170
public static byte max(byte... array)
171
public static double max(double... array)
172
public static float max(float... array)
173
public static int max(int... array)
174
public static long max(long... array)
175
public static short max(short... array)
176
```
177
178
**Usage Examples:**
179
```java { .api }
180
// Finding minimum values
181
int minInt = NumberUtils.min(5, 2, 8, 1, 9); // 1
182
double minDouble = NumberUtils.min(3.14, 2.71, 1.41); // 1.41
183
long minLong = NumberUtils.min(100L, 200L, 50L); // 50L
184
185
// Finding maximum values
186
int maxInt = NumberUtils.max(5, 2, 8, 1, 9); // 9
187
float maxFloat = NumberUtils.max(1.1f, 2.2f, 3.3f); // 3.3f
188
189
// Handling single element arrays
190
int single = NumberUtils.min(42); // 42
191
int singleMax = NumberUtils.max(42); // 42
192
```
193
194
### Range Classes - Range Operations and Validation
195
196
Apache Commons Lang provides several Range implementations for different numeric types:
197
198
#### Range<T> - Generic Range Operations
199
200
```java { .api }
201
import org.apache.commons.lang3.Range;
202
```
203
204
```java { .api }
205
// Range creation methods
206
public static <T extends Comparable<? super T>> Range<T> between(T fromInclusive, T toInclusive)
207
public static <T> Range<T> between(T fromInclusive, T toInclusive, Comparator<T> comparator)
208
public static <T extends Comparable<? super T>> Range<T> is(T element)
209
public static <T> Range<T> is(T element, Comparator<T> comparator)
210
211
// Range operations
212
public boolean contains(T element)
213
public boolean containsRange(Range<T> otherRange)
214
public boolean isOverlappedBy(Range<T> otherRange)
215
public T getMinimum()
216
public T getMaximum()
217
public Comparator<T> getComparator()
218
```
219
220
**Usage Examples:**
221
```java { .api }
222
// Creating ranges
223
Range<Integer> ageRange = Range.between(18, 65); // 18 to 65 inclusive
224
Range<String> nameRange = Range.between("A", "M"); // Alphabetical range A-M
225
Range<Integer> exact = Range.is(42); // Exact value range
226
227
// Range validation
228
boolean inRange = ageRange.contains(25); // true
229
boolean tooYoung = ageRange.contains(16); // false
230
boolean validName = nameRange.contains("John"); // true
231
232
// Range relationships
233
Range<Integer> overlap = Range.between(60, 70);
234
boolean overlaps = ageRange.isOverlappedBy(overlap); // true
235
boolean contains = ageRange.containsRange(Range.between(20, 30)); // true
236
237
// Range boundaries
238
Integer min = ageRange.getMinimum(); // 18
239
Integer max = ageRange.getMaximum(); // 65
240
```
241
242
#### IntegerRange - Integer-Specific Range
243
244
```java { .api }
245
import org.apache.commons.lang3.IntegerRange;
246
```
247
248
```java { .api }
249
// Integer range creation
250
public static IntegerRange of(int fromInclusive, int toInclusive)
251
public static IntegerRange of(Integer fromInclusive, Integer toInclusive)
252
```
253
254
**Usage Examples:**
255
```java { .api }
256
// Integer ranges
257
IntegerRange scoreRange = IntegerRange.of(0, 100);
258
IntegerRange passingRange = IntegerRange.of(60, 100);
259
260
// Validation
261
boolean validScore = scoreRange.contains(85); // true
262
boolean passing = passingRange.contains(85); // true
263
boolean failing = passingRange.contains(45); // false
264
265
// Range operations
266
int minScore = scoreRange.getMinimum(); // 0
267
int maxScore = scoreRange.getMaximum(); // 100
268
```
269
270
#### LongRange and DoubleRange
271
272
```java { .api }
273
import org.apache.commons.lang3.LongRange;
274
import org.apache.commons.lang3.DoubleRange;
275
```
276
277
```java { .api }
278
// Long range operations
279
LongRange timestampRange = LongRange.of(1000000L, 9999999L);
280
boolean validTimestamp = timestampRange.contains(5000000L); // true
281
282
// Double range operations
283
DoubleRange temperatureRange = DoubleRange.of(-40.0, 50.0);
284
boolean validTemp = temperatureRange.contains(23.5); // true
285
boolean tooHot = temperatureRange.contains(75.0); // false
286
```
287
288
### Fraction - Fraction Arithmetic
289
290
Provides exact fraction arithmetic without floating-point precision issues:
291
292
```java { .api }
293
import org.apache.commons.lang3.math.Fraction;
294
```
295
296
#### Fraction Constants
297
298
```java { .api }
299
// Predefined fraction constants
300
public static final Fraction ZERO = new Fraction(0, 1)
301
public static final Fraction ONE = new Fraction(1, 1)
302
public static final Fraction ONE_HALF = new Fraction(1, 2)
303
public static final Fraction ONE_THIRD = new Fraction(1, 3)
304
public static final Fraction TWO_THIRDS = new Fraction(2, 3)
305
public static final Fraction ONE_QUARTER = new Fraction(1, 4)
306
public static final Fraction TWO_QUARTERS = new Fraction(2, 4)
307
public static final Fraction THREE_QUARTERS = new Fraction(3, 4)
308
public static final Fraction ONE_FIFTH = new Fraction(1, 5)
309
public static final Fraction TWO_FIFTHS = new Fraction(2, 5)
310
public static final Fraction THREE_FIFTHS = new Fraction(3, 5)
311
public static final Fraction FOUR_FIFTHS = new Fraction(4, 5)
312
```
313
314
#### Fraction Creation and Operations
315
316
```java { .api }
317
// Fraction creation
318
public static Fraction getFraction(int numerator, int denominator)
319
public static Fraction getFraction(int whole, int numerator, int denominator)
320
public static Fraction getFraction(double value)
321
public static Fraction getFraction(String str)
322
323
// Arithmetic operations
324
public Fraction add(Fraction fraction)
325
public Fraction subtract(Fraction fraction)
326
public Fraction multiply(Fraction fraction)
327
public Fraction divide(Fraction fraction)
328
public Fraction pow(int power)
329
public Fraction abs()
330
public Fraction negate()
331
```
332
333
**Usage Examples:**
334
```java { .api }
335
// Creating fractions
336
Fraction half = Fraction.ONE_HALF; // 1/2
337
Fraction third = Fraction.getFraction(1, 3); // 1/3
338
Fraction mixed = Fraction.getFraction(2, 1, 4); // 2 1/4 = 9/4
339
Fraction fromDouble = Fraction.getFraction(0.75); // 3/4
340
Fraction fromString = Fraction.getFraction("2/3"); // 2/3
341
342
// Arithmetic operations
343
Fraction sum = half.add(third); // 1/2 + 1/3 = 5/6
344
Fraction difference = third.subtract(Fraction.ONE_QUARTER); // 1/3 - 1/4 = 1/12
345
Fraction product = half.multiply(third); // 1/2 * 1/3 = 1/6
346
Fraction quotient = half.divide(third); // 1/2 ÷ 1/3 = 3/2
347
348
// Powers and signs
349
Fraction squared = half.pow(2); // (1/2)² = 1/4
350
Fraction absolute = Fraction.getFraction(-3, 4).abs(); // 3/4
351
Fraction negated = half.negate(); // -1/2
352
```
353
354
#### Fraction Conversion and Comparison
355
356
```java { .api }
357
// Conversion methods
358
public int getNumerator()
359
public int getDenominator()
360
public double doubleValue()
361
public float floatValue()
362
public int intValue()
363
public long longValue()
364
365
// Comparison methods
366
public int compareTo(Fraction other)
367
public boolean equals(Object obj)
368
```
369
370
**Usage Examples:**
371
```java { .api }
372
// Accessing fraction parts
373
Fraction frac = Fraction.getFraction(3, 4);
374
int numerator = frac.getNumerator(); // 3
375
int denominator = frac.getDenominator(); // 4
376
377
// Converting to primitive types
378
double decimal = frac.doubleValue(); // 0.75
379
float floatVal = frac.floatValue(); // 0.75f
380
int rounded = frac.intValue(); // 0 (truncated)
381
382
// Comparison
383
Fraction a = Fraction.ONE_HALF;
384
Fraction b = Fraction.ONE_THIRD;
385
int comparison = a.compareTo(b); // 1 (1/2 > 1/3)
386
boolean equal = a.equals(Fraction.getFraction(2, 4)); // true (equivalent fractions)
387
```
388
389
## Advanced Mathematical Operations
390
391
### IEEE754rUtils - IEEE 754 Compliant Operations
392
393
Provides IEEE 754-compliant min/max operations that handle NaN correctly:
394
395
```java { .api }
396
import org.apache.commons.lang3.math.IEEE754rUtils;
397
```
398
399
```java { .api }
400
// IEEE 754 compliant min/max operations
401
public static double min(double... array)
402
public static float min(float... array)
403
public static double max(double... array)
404
public static float max(float... array)
405
```
406
407
**Usage Examples:**
408
```java { .api }
409
// Proper handling of NaN values
410
double min1 = IEEE754rUtils.min(1.0, Double.NaN, 3.0); // 1.0 (ignores NaN)
411
double max1 = IEEE754rUtils.max(1.0, Double.NaN, 3.0); // 3.0 (ignores NaN)
412
413
// Compare with regular Math.min/max
414
double regularMin = Math.min(1.0, Double.NaN); // NaN (incorrect)
415
double ieee754Min = IEEE754rUtils.min(1.0, Double.NaN); // 1.0 (correct)
416
```
417
418
### Custom Range Implementations
419
420
```java { .api }
421
public class CustomRanges {
422
423
// Percentage range validation
424
public static class PercentageRange {
425
private static final DoubleRange PERCENTAGE = DoubleRange.of(0.0, 100.0);
426
427
public static boolean isValidPercentage(double value) {
428
return PERCENTAGE.contains(value);
429
}
430
431
public static void validatePercentage(double value) {
432
Validate.isTrue(isValidPercentage(value),
433
"Percentage must be between 0 and 100, got: %f", value);
434
}
435
}
436
437
// Port number range validation
438
public static class PortRange {
439
private static final IntegerRange VALID_PORTS = IntegerRange.of(1, 65535);
440
private static final IntegerRange WELL_KNOWN_PORTS = IntegerRange.of(1, 1023);
441
442
public static boolean isValidPort(int port) {
443
return VALID_PORTS.contains(port);
444
}
445
446
public static boolean isWellKnownPort(int port) {
447
return WELL_KNOWN_PORTS.contains(port);
448
}
449
}
450
451
// Date range operations
452
public static class DateRange {
453
public static Range<LocalDate> between(LocalDate start, LocalDate end) {
454
return Range.between(start, end);
455
}
456
457
public static boolean isWeekend(LocalDate date) {
458
DayOfWeek dayOfWeek = date.getDayOfWeek();
459
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
460
}
461
462
public static boolean isInCurrentMonth(LocalDate date) {
463
LocalDate now = LocalDate.now();
464
Range<LocalDate> currentMonth = Range.between(
465
now.withDayOfMonth(1),
466
now.withDayOfMonth(now.lengthOfMonth())
467
);
468
return currentMonth.contains(date);
469
}
470
}
471
}
472
```
473
474
### Number Formatting and Parsing Utilities
475
476
```java { .api }
477
public class NumberFormatUtils {
478
479
// Safe number parsing with multiple formats
480
public static OptionalInt parseIntSafely(String value) {
481
if (StringUtils.isBlank(value)) {
482
return OptionalInt.empty();
483
}
484
485
// Try different formats
486
String cleaned = StringUtils.strip(value);
487
488
// Remove common formatting
489
cleaned = StringUtils.remove(cleaned, ',');
490
cleaned = StringUtils.remove(cleaned, ' ');
491
492
if (NumberUtils.isCreatable(cleaned)) {
493
try {
494
return OptionalInt.of(NumberUtils.createNumber(cleaned).intValue());
495
} catch (NumberFormatException e) {
496
return OptionalInt.empty();
497
}
498
}
499
500
return OptionalInt.empty();
501
}
502
503
// Parse with validation
504
public static int parseIntInRange(String value, IntegerRange range, int defaultValue) {
505
OptionalInt parsed = parseIntSafely(value);
506
if (parsed.isPresent() && range.contains(parsed.getAsInt())) {
507
return parsed.getAsInt();
508
}
509
return defaultValue;
510
}
511
512
// Currency amount parsing
513
public static BigDecimal parseCurrency(String amount) {
514
if (StringUtils.isBlank(amount)) {
515
return BigDecimal.ZERO;
516
}
517
518
// Remove currency symbols and whitespace
519
String cleaned = amount.replaceAll("[^0-9.-]", "");
520
521
try {
522
return NumberUtils.createBigDecimal(cleaned);
523
} catch (NumberFormatException e) {
524
throw new IllegalArgumentException("Invalid currency amount: " + amount, e);
525
}
526
}
527
}
528
```
529
530
## Performance Optimization
531
532
### Efficient Number Operations
533
534
```java { .api }
535
public class EfficientMathOperations {
536
537
// Cache commonly used ranges
538
private static final Map<String, IntegerRange> RANGE_CACHE = Map.of(
539
"age", IntegerRange.of(0, 150),
540
"percentage", IntegerRange.of(0, 100),
541
"score", IntegerRange.of(0, 100),
542
"priority", IntegerRange.of(1, 10)
543
);
544
545
// Reuse range instances
546
public static boolean isValidAge(int age) {
547
return RANGE_CACHE.get("age").contains(age);
548
}
549
550
// Bulk validation
551
public static List<Integer> filterValidNumbers(String[] inputs, IntegerRange validRange) {
552
return Arrays.stream(inputs)
553
.filter(StringUtils::isNotBlank)
554
.filter(NumberUtils::isCreatable)
555
.mapToInt(NumberUtils::toInt)
556
.filter(validRange::contains)
557
.boxed()
558
.collect(Collectors.toList());
559
}
560
561
// Avoid repeated parsing
562
public static class NumberCache {
563
private final Map<String, Number> cache = new ConcurrentHashMap<>();
564
565
public Number getOrParse(String value) {
566
return cache.computeIfAbsent(value, v -> {
567
if (NumberUtils.isCreatable(v)) {
568
return NumberUtils.createNumber(v);
569
}
570
return NumberUtils.INTEGER_ZERO;
571
});
572
}
573
}
574
}
575
```
576
577
## Integration Examples
578
579
### Validation Framework Integration
580
581
```java { .api }
582
@Component
583
public class NumericValidator {
584
585
public void validateScore(Integer score) {
586
Validate.notNull(score, "Score cannot be null");
587
588
IntegerRange validScore = IntegerRange.of(0, 100);
589
Validate.isTrue(validScore.contains(score),
590
"Score must be between 0 and 100, got: %d", score);
591
}
592
593
public void validateTemperature(String tempStr) {
594
Validate.notBlank(tempStr, "Temperature cannot be blank");
595
596
double temp = NumberUtils.toDouble(tempStr, Double.NaN);
597
Validate.isTrue(!Double.isNaN(temp), "Invalid temperature format: %s", tempStr);
598
599
DoubleRange validRange = DoubleRange.of(-273.15, 1000.0); // Celsius
600
Validate.isTrue(validRange.contains(temp),
601
"Temperature out of valid range: %f", temp);
602
}
603
604
public Fraction validateFraction(String fractionStr) {
605
Validate.notBlank(fractionStr, "Fraction cannot be blank");
606
607
try {
608
Fraction fraction = Fraction.getFraction(fractionStr);
609
Validate.notNull(fraction, "Invalid fraction format: %s", fractionStr);
610
return fraction;
611
} catch (NumberFormatException e) {
612
throw new IllegalArgumentException("Invalid fraction: " + fractionStr, e);
613
}
614
}
615
}
616
```
617
618
### Configuration Value Processing
619
620
```java { .api }
621
@Configuration
622
public class MathConfiguration {
623
624
@Value("${app.min-age:18}")
625
private String minAgeStr;
626
627
@Value("${app.max-age:65}")
628
private String maxAgeStr;
629
630
@Bean
631
public IntegerRange ageRange() {
632
int minAge = NumberUtils.toInt(minAgeStr, 18);
633
int maxAge = NumberUtils.toInt(maxAgeStr, 65);
634
635
Validate.isTrue(minAge < maxAge, "Min age must be less than max age");
636
637
return IntegerRange.of(minAge, maxAge);
638
}
639
640
@Bean
641
public DoubleRange temperatureRange(@Value("${app.min-temp:-40}") String minTemp,
642
@Value("${app.max-temp:50}") String maxTemp) {
643
double min = NumberUtils.toDouble(minTemp, -40.0);
644
double max = NumberUtils.toDouble(maxTemp, 50.0);
645
646
return DoubleRange.of(min, max);
647
}
648
}
649
```
650
651
The math utilities in Apache Commons Lang provide robust, null-safe mathematical operations with proper handling of edge cases, making numerical computations more reliable and maintainable in Java applications.