Skip to content

Commit

Permalink
issue #288 : fix random BigDecimal generation
Browse files Browse the repository at this point in the history
Random BigDecimal generation  was based on long instead of double.
When specifying a min as 0.01, a min of 0 was used.
This commit fixes the issue by using the double type to avoid any data
precision loss.
  • Loading branch information
fmbenhassine committed Nov 18, 2018
1 parent f7f685c commit fd378c9
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ public Randomizer<?> getRandomizer(Field field) {
}
if (fieldType.equals(BigDecimal.class)) {
return new BigDecimalRangeRandomizer(
minValue == null ? null : minValue.longValue(),
maxValue == null ? null : maxValue.longValue(),
minValue == null ? null : minValue.doubleValue(),
maxValue == null ? null : maxValue.doubleValue(),
random.nextLong()
);
}
if (fieldType.equals(String.class)) {
BigDecimalRangeRandomizer delegate = new BigDecimalRangeRandomizer(
minValue == null ? null : minValue.longValue(),
maxValue == null ? null : maxValue.longValue(),
minValue == null ? null : minValue.doubleValue(),
maxValue == null ? null : maxValue.doubleValue(),
random.nextLong()
);
return new StringDelegatingRandomizer(delegate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,18 +163,18 @@ public void shouldGenerateTheSameValueForTheSameSeed() {
// assertThat(bean.getBirthday()).isEqualTo("2007-07-22T13:20:35.628");
// uses DateRange with now as start, so test is not repeatable
// assertThat(bean.getEventDate()).isEqualTo("2017-07-22T13:20:35.628");
assertThat(bean.getMaxQuantity()).isEqualTo(-2055951746);
assertThat(bean.getMaxQuantity()).isEqualTo(-2055951745);
assertThat(bean.getMinQuantity()).isEqualTo(91531906);
assertThat(bean.getMaxDiscount()).isEqualTo(new BigDecimal(30));
assertThat(bean.getMinDiscount()).isEqualTo(new BigDecimal(393126525614007301L));
//assertThat(bean.getDiscount()).isEqualTo(new BigDecimal(/* todo add assertion on actual value with the current seed */));
assertThat(bean.getMaxDiscount()).isEqualTo(new BigDecimal(1.2786858993971550457757757612853311002254486083984375));
assertThat(bean.getMinDiscount()).isEqualTo(new BigDecimal(7662282876638370609146101740543801632384371011755725427644785896281033154465107481014236865090602870006608143292003443098160947481248487711461114361337135608579588927391230902925850523644737673724379044725003237691291118781433336121334962263919251188630152674215174880065707256545268445171714648124229156864D));
assertThat(bean.getDiscount()).isEqualTo(new BigDecimal(0.182723708049134681008496272625052370131015777587890625));
assertThat(bean.getMinQuantity()).isEqualTo(91531906);
assertThat(bean.getBriefMessage()).isEqualTo("tguu");
assertThat(bean.getRegexString()).isEqualTo("vuna");
assertThat(bean.getPositive()).isEqualTo(91531902);
assertThat(bean.getPositiveOrZero()).isEqualTo(91531901);
assertThat(bean.getNegative()).isEqualTo(-2055951747);
assertThat(bean.getNegativeOrZero()).isEqualTo(-2055951747);
assertThat(bean.getNegative()).isEqualTo(-2055951746);
assertThat(bean.getNegativeOrZero()).isEqualTo(-2055951746);
assertThat(bean.getEmail()).isEqualTo("jeffery.wuckert@yahoo.com");
assertThat(bean.getNotBlank()).isEqualTo("tg");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected AbstractRangeRandomizer(final T min, final T max, final long seed) {
checkValues();
}

@Deprecated
protected long nextLong(final long min, final long max) {
long value = min + ((long) (random.nextDouble() * (max - min)));
if (value < min) {
Expand All @@ -61,6 +62,17 @@ protected long nextLong(final long min, final long max) {
}
}

protected double nextDouble(final double min, final double max) {
double value = min + (random.nextDouble() * (max - min));
if (value < min) {
return min;
} else if (value > max) {
return max;
} else {
return value;
}
}

protected abstract void checkValues();

protected abstract T getDefaultMinValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
*/
public class BigDecimalRangeRandomizer implements Randomizer<BigDecimal> {

private final LongRangeRandomizer delegate;
private final DoubleRangeRandomizer delegate;
private Integer scale;

/**
Expand All @@ -44,8 +44,19 @@ public class BigDecimalRangeRandomizer implements Randomizer<BigDecimal> {
* @param min min value
* @param max max value
*/
@Deprecated
public BigDecimalRangeRandomizer(final Long min, final Long max) {
delegate = new LongRangeRandomizer(min, max);
delegate = new DoubleRangeRandomizer(min.doubleValue(), max.doubleValue());
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.
*
* @param min min value
* @param max max value
*/
public BigDecimalRangeRandomizer(final Double min, final Double max) {
delegate = new DoubleRangeRandomizer(min, max);
}

/**
Expand All @@ -55,8 +66,20 @@ public BigDecimalRangeRandomizer(final Long min, final Long max) {
* @param max max value
* @param seed initial seed
*/
@Deprecated
public BigDecimalRangeRandomizer(final Long min, final Long max, final long seed) {
delegate = new LongRangeRandomizer(min, max, seed);
delegate = new DoubleRangeRandomizer(min.doubleValue(), max.doubleValue(), seed);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.
*
* @param min min value
* @param max max value
* @param seed initial seed
*/
public BigDecimalRangeRandomizer(final Double min, final Double max, final long seed) {
delegate = new DoubleRangeRandomizer(min, max, seed);
}

/**
Expand All @@ -66,8 +89,21 @@ public BigDecimalRangeRandomizer(final Long min, final Long max, final long seed
* @param max max value
* @param scale of the {@code BigDecimal} value to be returned.
*/
@Deprecated
public BigDecimalRangeRandomizer(final Long min, final Long max, final Integer scale) {
delegate = new LongRangeRandomizer(min, max);
delegate = new DoubleRangeRandomizer(min.doubleValue(), max.doubleValue());
this.scale = scale;
}

/**
* Create a new {@link BigDecimalRangeRandomizer}. The default rounding mode is {@link RoundingMode#HALF_UP}.
*
* @param min min value
* @param max max value
* @param scale of the {@code BigDecimal} value to be returned.
*/
public BigDecimalRangeRandomizer(final Double min, final Double max, final Integer scale) {
delegate = new DoubleRangeRandomizer(min, max);
this.scale = scale;
}

Expand All @@ -78,10 +114,22 @@ public BigDecimalRangeRandomizer(final Long min, final Long max, final Integer s
* @param max max value
* @return a new {@link BigDecimalRangeRandomizer}.
*/
@Deprecated
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Long min, final Long max) {
return new BigDecimalRangeRandomizer(min, max);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.
*
* @param min min value
* @param max max value
* @return a new {@link BigDecimalRangeRandomizer}.
*/
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Double min, final Double max) {
return new BigDecimalRangeRandomizer(min, max);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.
*
Expand All @@ -90,10 +138,23 @@ public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Long
* @param seed initial seed
* @return a new {@link BigDecimalRangeRandomizer}.
*/
@Deprecated
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Long min, final Long max, final long seed) {
return new BigDecimalRangeRandomizer(min, max, seed);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.
*
* @param min min value
* @param max max value
* @param seed initial seed
* @return a new {@link BigDecimalRangeRandomizer}.
*/
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Double min, final Double max, final long seed) {
return new BigDecimalRangeRandomizer(min, max, seed);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}.The default rounding mode is {@link RoundingMode#HALF_UP}.
*
Expand All @@ -102,15 +163,29 @@ public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Long
* @param scale of the {@code BigDecimal} value to be returned.
* @return a new {@link BigDecimalRangeRandomizer}.
*/
@Deprecated
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Long min, final Long max, final Integer scale) {
return new BigDecimalRangeRandomizer(min, max, scale);
}

/**
* Create a new {@link BigDecimalRangeRandomizer}. The default rounding mode is {@link RoundingMode#HALF_UP}.
*
* @param min min value
* @param max max value
* @param scale of the {@code BigDecimal} value to be returned.
* @return a new {@link BigDecimalRangeRandomizer}.
*/
public static BigDecimalRangeRandomizer aNewBigDecimalRangeRandomizer(final Double min, final Double max, final Integer scale) {
return new BigDecimalRangeRandomizer(min, max, scale);
}

@Override
public BigDecimal getRandomValue() {
BigDecimal randomValue = new BigDecimal(delegate.getRandomValue());
Double delegateRandomValue = delegate.getRandomValue();
BigDecimal randomValue = new BigDecimal(delegateRandomValue);
if (scale != null) {
randomValue = randomValue.setScale(this.scale, RoundingMode.HALF_UP);
randomValue = randomValue.setScale(this.scale, RoundingMode.HALF_UP); // FIXME As of v3.8, there is no way to configure RoundingMode
}
return randomValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected void checkValues() {

@Override
public Byte getRandomValue() {
return (byte) nextLong(min, max);
return (byte) nextDouble(min, max);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected Date getDefaultMaxValue() {
public Date getRandomValue() {
long minDateTime = min.getTime();
long maxDateTime = max.getTime();
long randomDateTime = nextLong(minDateTime, maxDateTime);
long randomDateTime = (long) nextDouble((double) minDateTime, (double) maxDateTime);
return new Date(randomDateTime);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,12 @@
*/
package io.github.benas.randombeans.randomizers.range;

import io.github.benas.randombeans.api.Randomizer;

import static java.lang.String.valueOf;

/**
* Generate a random {@link Double} in the given range.
*
* @author Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
*/
public class DoubleRangeRandomizer implements Randomizer<Double> {

private final LongRangeRandomizer delegate;
public class DoubleRangeRandomizer extends AbstractRangeRandomizer<Double> {

/**
* Create a new {@link DoubleRangeRandomizer}.
Expand All @@ -43,7 +37,7 @@ public class DoubleRangeRandomizer implements Randomizer<Double> {
* @param max max value
*/
public DoubleRangeRandomizer(final Double min, final Double max) {
delegate = new LongRangeRandomizer(min != null ? min.longValue() : null, max != null ? max.longValue() : null);
super(min, max);
}

/**
Expand All @@ -54,7 +48,24 @@ public DoubleRangeRandomizer(final Double min, final Double max) {
* @param seed initial seed
*/
public DoubleRangeRandomizer(final Double min, final Double max, final long seed) {
delegate = new LongRangeRandomizer(min != null ? min.longValue() : null, max != null ? max.longValue() : null, seed);
super(min, max, seed);
}

@Override
protected void checkValues() {
if (min > max) {
throw new IllegalArgumentException("max must be greater than min");
}
}

@Override
protected Double getDefaultMinValue() {
return Double.MIN_VALUE;
}

@Override
protected Double getDefaultMaxValue() {
return Double.MAX_VALUE;
}

/**
Expand Down Expand Up @@ -82,6 +93,6 @@ public static DoubleRangeRandomizer aNewDoubleRangeRandomizer(final Double min,

@Override
public Double getRandomValue() {
return new Double(valueOf(delegate.getRandomValue()));
return nextDouble(min, max);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected void checkValues() {

@Override
public Integer getRandomValue() {
return (int) nextLong(min, max);
return (int) nextDouble(min, max);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected LocalDate getDefaultMaxValue() {
public LocalDate getRandomValue() {
long minEpochDay = min.getLong(ChronoField.EPOCH_DAY);
long maxEpochDay = max.getLong(ChronoField.EPOCH_DAY);
long randomEpochDay = nextLong(minEpochDay, maxEpochDay);
long randomEpochDay = (long) nextDouble(minEpochDay, maxEpochDay);
return LocalDate.ofEpochDay(randomEpochDay);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected LocalTime getDefaultMaxValue() {
public LocalTime getRandomValue() {
long minSecondOfDay = min.getLong(ChronoField.SECOND_OF_DAY);
long maxSecondOfDay = max.getLong(ChronoField.SECOND_OF_DAY);
long randomSecondOfDay = nextLong(minSecondOfDay, maxSecondOfDay);
long randomSecondOfDay = (long) nextDouble(minSecondOfDay, maxSecondOfDay);
return LocalTime.ofSecondOfDay(randomSecondOfDay);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected void checkValues() {

@Override
public Long getRandomValue() {
return nextLong(min, max);
return (long) nextDouble(min, max);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected void checkValues() {

@Override
public Short getRandomValue() {
return (short) nextLong(min, max);
return (short) nextDouble(min, max);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected Date getDefaultMaxValue() {
public Date getRandomValue() {
long minDateTime = min.getTime();
long maxDateTime = max.getTime();
long randomDateTime = nextLong(minDateTime, maxDateTime);
long randomDateTime = (long) nextDouble(minDateTime, maxDateTime);
return new Date(randomDateTime);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ protected ZonedDateTime getDefaultMaxValue() {
public ZonedDateTime getRandomValue() {
long minSeconds = min.toEpochSecond();
long maxSeconds = max.toEpochSecond();
long seconds = nextLong(minSeconds, maxSeconds);
long seconds = (long) nextDouble(minSeconds, maxSeconds);
int minNanoSeconds = min.getNano();
int maxNanoSeconds = max.getNano();
long nanoSeconds = nextLong(minNanoSeconds, maxNanoSeconds);
long nanoSeconds = (long) nextDouble(minNanoSeconds, maxNanoSeconds);
return ZonedDateTime.ofInstant(Instant.ofEpochSecond(seconds, nanoSeconds), min.getZone());
}

Expand Down
Loading

0 comments on commit fd378c9

Please sign in to comment.