Подтвердить что ты не робот

Как получить десятичную часть поплавка?

Мне нужно извлечь десятичную часть числа с плавающей точкой, но я получаю странные результаты:

float n = 22.65f;
// I want x = 0.65f, but...

x = n % 1; // x = 0.6499996

x = n - Math.floor(n); // x = 0.6499996185302734

x = n - (int)n; // x = 0.6499996

Почему это происходит? Почему я получаю эти значения вместо 0.65?

4b9b3361

Ответ 1

float имеет только несколько цифр точности, поэтому вы можете ожидать, что круглую ошибку достаточно легко. try double это имеет большую точность, но все еще имеет ошибки округления. Вы должны округлить любой ответ, который вы получите, чтобы получить разумный результат.

Если это нежелательно, вы можете использовать BigDecimal, который не имеет ошибок округления, но имеет свои собственные головные боли IMHO.

РЕДАКТ: Вы можете найти это интересным. По умолчанию Float.toString() использует минимальное округление, но часто его недостаточно.

System.out.println("With no rounding");
float n = 22.65f;
System.out.println("n= "+new BigDecimal(n));
float expected = 0.65f;
System.out.println("expected= "+new BigDecimal(expected));

System.out.println("n % 1= "+new BigDecimal(n % 1));
System.out.println("n - Math.floor(n) = "+new BigDecimal(n - Math.floor(n)));
System.out.println("n - (int)n= "+new BigDecimal(n - (int)n));

System.out.println("With rounding");
System.out.printf("n %% 1= %.2f%n", n % 1);
System.out.printf("n - Math.floor(n) = %.2f%n", n - Math.floor(n));
System.out.printf("n - (int)n= %.2f%n", n - (int)n);

Печать

With no rounding
n= 22.6499996185302734375
expected= 0.64999997615814208984375
n % 1= 0.6499996185302734375
n - Math.floor(n) = 0.6499996185302734375
n - (int)n= 0.6499996185302734375
With rounding
n % 1= 0.65
n - Math.floor(n) = 0.65
n - (int)n= 0.65

Ответ 2

Я думаю, что это было бы самым простым способом:

float n = 22.65f;
float x = n - (int) n;

Ответ 3

Потому что не все рациональные числа могут быть представлены как число с плавающей запятой, а 0.6499996... является ближайшим приближением для 0.65.

Например, попробуйте напечатать первые 20 цифр номера 0.65:

 System.out.printf("%.20f\n", 0.65f);

- >

 0.64999997615814210000

изменить
Ошибки округления, которые накапливаются во время вычислений, также играют в этом роль, как отмечали другие.

Ответ 4

Я немного устал, но работает:

BigDecimal.valueOf(2.65d).divideAndRemainder(BigDecimal.ONE)[1].floatValue()

Ответ 5

Если вы просто хотите напечатать номер до 2dp, вы можете использовать DecimalFormat.

DecimalFormat df= new DecimalFormat("#.##");
System.out.println(df.format(f));

Если вы хотите, чтобы фиксированные номера точек внутренне использовали BigDecimal

Ответ 6

Попробуйте это. Если таймер равен 10.65, то h заканчивается как первые два десятичных знака * 100 = 65.

Это быстрый и простой способ отделить то, что вы хотите, без проблем округления.

float h = (int)((timer % 1) * 100);

Ответ 7

Звук и отличный способ получить десятичную часть float и двойных типов данных используют с String, как этот код:

float num=2.35f;
String s= new Float(num).toString();
String p=s.substring(s.indexOf('.')+1,s.length());
int decimal=Integer.parseInt(p);

Ответ 10

Этот код будет работать для любого количества десятичных цифр.

float f = 2.3445f;
String s = Float.toString(f);
char[] c = s.toCharArray();
int length = s.length();
int flag = 0;
StringBuilder n = new StringBuilder();
for(int i = 0; i < length; i++)
{
    if(flag == 1)
    {
        n.append(c[i]);
    }
    if(c[i] == '.')
    {
        flag = 1;
    }
}
String result = n.toString();
int answer = Integer.parseInt(result);
System.out.println(answer);