1

I want to get a class which provides a range of decimal values.

Due to specification of floating point number, returned range object doesn't have accurate values.

To get more precise result like [0.60,0.61,0.62...0.69] returned by python's numpy.arange(0.6,0.7,0.01)

my code is shown below.

// Java range
public class range{

    private double start;
    private double end;
    private double step;

    public range(double start,double end, double step) {
        this.start = start;
        this.end = end;
        this.step = step;
    }

    public List<Double> asList(){
        List<Double> ret = new ArrayList<Double>();
        for(double i = this.start;i <= this.end; i += this.step){
            ret.add(i);
        }
        return ret;
    }   
}

Could you have any idea or smarter way to avoid the problem?

And, I hope to get the implementation with only java standard library.

ric
  • 119
  • 1
  • 2
  • 9
  • 1
    show input/output, if it's just arbitrary floating point sneaking in then you can use `BigDecimal` (arbitrary precision) or if you just need rounded numbers you can multiply/floor/divide it. – Rogue Mar 24 '17 at 05:37
  • @Rogue Thank you for your information. On this time, I just need rounded numbers. But, I will fix my class using BigDecimal for the future. – ric Mar 24 '17 at 06:00

2 Answers2

0

You won't get a number like 0.60 when simply printing a Float or Double in java. However you can format these values into appropriate String values while printing them.

So either...

  1. you can change the return type of asList() to List<String> and add in it your preferred format.
  2. or you can change how this Double value in your List is displayed in your main Driver class.

The first option can be implemented if you change your method to this

...
public List<String> asList(){
    List<String> ret = new ArrayList<String>();
    for(double i = this.start; i <= this.end; i += this.step){
        ret.add(String.format("%.2f", i));
    }
    return ret;
}
....

I have used String.format() here, but there are several other options described in this answer.

Community
  • 1
  • 1
Raman Sahasi
  • 24,890
  • 6
  • 51
  • 66
  • 1
    Thank you for your simple but complete answer. – ric Mar 24 '17 at 05:50
  • @ric just be careful, you might get strange behaviour where there might be one extra or one fewer answer than what you expect if you're just changing the output format. Take Rogue's suggestion to use a library specifically tailored for decimals if you want to be more exact here – muzzlator Mar 24 '17 at 05:52
  • @muzzlator I understand. Thanks for your comment. – ric Mar 24 '17 at 06:03
0

In this version, you can get a list of (start, end, step) as python has.


class Range implements Iterable {

private int limit;
private double start;
private double end;
private double step;

public Range(int limit) {
    this.limit = limit;
}

public Range(double start,double end, double step) {
    this.start = start;
    this.end = end;
    this.step = step;
}

public List<String> asList(){
    List<String> ret = new ArrayList<String>();
    for(double i = this.start; i <= this.end; i += this.step){
        ret.add(String.format("%.2f", i));
    }
    return ret;
}

@Override
public Iterator<Integer> iterator() {
    final int max = limit;
    return new Iterator<Integer>() {

        private int current = 0;

        @Override
        public boolean hasNext() {
            return current < max;
        }

        @Override
        public Integer next() {
            if (hasNext()) {
                return current++;   
            } else {
                throw new NoSuchElementException("Range reached the end");
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Can't remove values from a Range");
        }
    };
}

}

leroneb
  • 63
  • 4