they round up the number, and that’s not what I wish
Good, String.format
also round:
// quarta casa decimal é >= 5, arredonda para cima
System.out.println(String.format("%.3f", 1.2225)); // 1,223
// quarta casa decimal é < 5, arredonda para baixo
System.out.println(String.format("%.3f", 1.2224)); // 1,222
I believe that when you say "do not round up," you mean that the result should be 1,222
for both cases, right?
It is worth remembering that the decimal separator may be the comma or the point, depending on the default locale of the JVM, as already explained in another question. But when you use String.format
, rounding is always done, including this is said in documentation:
the value will be rounded using the round half up Algorithm
And the aforementioned rounding algorithm is described here.
Anyway, what exactly do you want to do?
If you want to get one float
only with the first 3 decimal places, then you just need to use good old math:
// manter apenas as N primeiras casas decimais
static float manterCasas(float valor, int qtdCasas) {
float fator = (float) Math.pow(10, qtdCasas);
return (float) (Math.floor(valor * fator) / fator);
}
public static void main(String[] args) {
// sempre mantém as 3 primeiras casas, sem arredondar
System.out.println(manterCasas(1.2225f, 3)); // 1.222
System.out.println(manterCasas(1.2224f, 3)); // 1.222
}
The idea to keep the N first houses is to multiply the number by 10N, round down and then divide by 10N (as explained above here and here).
But if you want one String
with the first 3 decimal places, controlling even the decimal separator, there you can use DecimalFormat
even:
public static void main(String[] args) {
System.out.println(formatar(1.2225f, 3)); // 1.222
System.out.println(formatar(1.2224f, 3)); // 1.222
}
static String formatar(float valor, int qtdCasas) {
NumberFormat fmt = DecimalFormat.getNumberInstance();
// limitar quantidade de casas decimais
fmt.setMaximumFractionDigits(qtdCasas);
// arredondar para baixo tem o mesmo efeito que "não arredondar a última casa decimal"
fmt.setRoundingMode(RoundingMode.DOWN);
return fmt.format(valor);
}
Remembering that the decimal separator can be the point or the comma, according to the default locale JVM. If you want a specific one, you can pass the locale to the NumberFormat
. Ex:
// usar locale pt-BR (português do Brasil) para o separador decimal ser a vírgula
NumberFormat fmt = DecimalFormat.getNumberInstance(new Locale("pt", "BR"));
Remembering that by default the thousands separator is also placed (1000
is formatted as 1.000
). If you want to disable that, do it fmt.setGroupingUsed(false);
.
Another detail is that if the number has less than 3 decimal places, not all of them will be shown. If you want to always show 3, just add fmt.setMinimumFractionDigits(qtdCasas);
.
Finally, it is worth remembering not to confuse a number with its representation. A number like 1,5
is only a numerical value... that has no format in itself (it is only a concept, an idea: it represents a certain value, only that). But this same number can be represented in several ways: as 1.5
, 1,5
, um e meio
, 000001.500
, etc..
That is, a numerical value stored in a float
(or int
, or double
, etc) has no format, but it can be converted to a string that represents this value in different ways. When I print the number, it is converted to a string in a given format (with println
, for example, I do not control the format, but with format
and DecimalFormat
yes). So it is important to know what you need: change the numerical value (generate another float
only with the first 3 decimal places) or just generate a string that represents the number with the first 3 houses.
You want to generate a string or a
float
with the first three decimal places? Although it seems, it is not the same thing, because "format" usually means "turn into string", can change the decimal separator and thousands, etc. Inclusive, this was the error:String.format
uses the default locale of the JVM, which in your case is one that uses the comma (I explained this already in your other question), andparseFloat
only recognizes the point.– hkotsubo
Anyway,
Decimalformat
has the option to change the form of rounding, test there (I think it’s theDOWN
, but see there). But if you want afloat
, I find it easier to do the same: https://answall.com/a/459884/112052. (this is in Javascript, but the idea is the same)– hkotsubo
Anyway 2:
String.format
round yes :-)– hkotsubo