-1

I need to process a CSV. The users define if a column has floats or doubles. The thing is, sometimes they put doubles in a float column, and after it rounds the values and the users only find out later.

I'd like to not let this behaviour happen if it's at all possible.

So, if we try to store a number too big on a float, it doesn't round it but instead throws an exception.

I'm aware that there are some numbers that cannot be represented correctly like when we do 0.1 + 0.2, this is not what I'm trying to avoid.

I've considered storing everything on a BigDecimal, but currently that has too much impact on the codebase so I'd prefer to avoid it for now.

Edit:

I'm aware there are rounding errors. But assuming the systems are using IEEE 754 floats or doubles, the representation is the same. So a "0.25" float in a system is going to continue to have the same rounding error after imported.

20
  • Will it be enough to check number of digits in your input? Commented Nov 15, 2024 at 16:43
  • You don’t have to store BigDecimals, just create one and compare against the largest float, then throw an exception. Commented Nov 15, 2024 at 16:48
  • @Sweeper that was my first inclination. Just not sure if that's the fastest way to compare it and the CSVs might have millions of rows. Commented Nov 15, 2024 at 16:49
  • @talexmovedtoCodidact Wouldn't this fail to catch some rounding cases that just change the last significant digit? Commented Nov 15, 2024 at 16:52
  • 2
    Your question doesn't make sense. What does 'I do not want rounding errors, but, also, 0.3 is fine' mean? I think you misunderstand a few things. Everything has rounding errors if you use float or double math. The only things that double/float can store without any loss is anything that can be expressed as X/2^Y where X can be whatever. So, 5/8ths can be stored perfectly (because 8 is 2*2*2). Think about decimal. The same thing happens there, except there it's X/(2^Y*5^Z) (because 2 and 5 are the divisors of 10, and decimal = base 10). Commented Nov 15, 2024 at 17:35

1 Answer 1

0

This is what I came up with. Didn't test much yet and need to check if it makes more sense BigDcimal compareTo or equals. I got the limits from this question.

import java.math.BigDecimal;

static boolean isRounded(String strNumber) {
float f = Float.parseFloat(strNumber);
BigDecimal bdf = BigDecimal.valueOf(f);
BigDecimal bd = new BigDecimal(strNumber);

// return bd.equals(bdf);
return bd.compareTo(bdf) != 0;
}

String ok = "16777216";
String nok = "16777217";
System.out.println("is rounded " + isRounded(ok)); // false
System.out.println("is rounded " + isRounded(nok)); // true
Sign up to request clarification or add additional context in comments.

2 Comments

The problem is this, consider 0.1. That will get truncated for a Float, but it doesn't get truncated for a BigDecimal. I would say your test isn't quite complete. Also float only contains a subset of int so you could have a value that is less than 16777216 but also not "rounded"
Yeah, was just finding the 0.1 issue. Also, want to check Float.MAX_VALUE.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.