Float и двойной тип данных в Java


220

Тип данных с плавающей запятой - это 32-битная плавающая точка IEEE 754 с одинарной точностью, а тип данных с двойной точностью - 64-битная плавающая точка IEEE 754 с двойной точностью.

Что это означает? И когда я должен использовать float вместо double или наоборот?


8
Вы должны использовать float вместо double, когда использование памяти критично. Если вам нужны более точные вычисления, используйте double.
Everv0id

12
@ Everv0id: Я не уверен ни в одной ситуации, в которой память была настолько ограничена, что приходилось жертвовать точностью ради космоса. (Вы пользуетесь Java , ради всего святого ...) Могут быть ситуации, когда это требуется, но в своей практике я видел это очень редко. Если вы хотите уточнить, почему вы считаете, что это хорошая идея, предоставление ответа, например, было бы достойным дополнением.
Макото


5
@ На самом деле Макото, я никогда не использовал поплавки, только удваивается. Но могут быть приложения (теоретически), которые должны хранить большое количество чисел с плавающей запятой, поэтому использование памяти в 2 раза может быть критическим. Теоретически, ofc; на практике вы всегда можете купить еще один сервер .
Everv0id

3
Я использовал 4-байтовые и даже 2-байтовые числа с фиксированной точностью для экономии памяти, но если у вас их нет, вряд ли это того стоит. Время, которое требуется вам, чтобы написать «double» вместо «float» (у него есть еще одна буква), стоит в 1000 раз больше используемой вами дополнительной памяти, но если вы используете, doubleа не floatспасаете вас от ошибки, связанной с точностью, это того стоит ,
Питер Лори

Ответы:


259

На странице Википедии это хорошее место для начала.

Подводить итоги:

  • floatпредставлен в 32 битах, с 1 знаковым битом, 8 битами показателя степени и 23 битами значащего (или того, что следует из числа научной нотации: 2.33728 * 10 12 ; 33728 является значащим).

  • double представляется в 64 битах, с 1 знаковым битом, 11 битами показателя степени и 52 битами значимости.

По умолчанию Java использует doubleдля представления своих чисел с плавающей точкой (поэтому литерал 3.14набирается double). Это также тип данных, который даст вам гораздо больший диапазон номеров, поэтому я настоятельно рекомендую использовать его более float.

Там могут быть некоторые библиотеки , которые на самом деле заставить ваше использование float, но в целом - если вы не можете гарантировать , что ваш результат будет достаточно мал , чтобы поместиться в float«s предписанного диапазона , то это лучше сделать выбор с double.

Если вам требуется точность - например, вы не можете иметь десятичное значение, которое является неточным (например 1/10 + 2/10), или вы делаете что- то с валютой (например, представляющей 10,33 $ в системе), тогда используйте a BigDecimal, который может поддерживать произвольное количество точности и элегантно обрабатывать подобные ситуации.


4
Разве не 233728 == мантисса в данном примере? Я имею в виду, где еще хранится целочисленная часть?
JaLoveAst1k

1
@ mathguy54: В научной нотации 2 будет целым числом, а .33728 будет мантиссой. Вот ссылка на это.
Макото

5
Я искал информацию о числах с плавающей и двойной чисел и нашел это, и мне нужно было это прокомментировать: если вы делаете что-то с валютой, которая не включает дробные центы, использование BigDecimal нелепо. Общая валюта - это дискретные данные, поэтому вы должны использовать целочисленный тип данных. (Это одна из наиболее распространенных ошибок, допущенных молодыми программистами - поскольку мы используем. Для отделения долларов от центов, они думают, что это значение с плавающей запятой. Это не так.)
Трикси Вольф

2
@ TrixieWolf, не могли бы вы конкретизировать, предлагали ли вы использовать два целых числа (целые и десятичные части)? А вы говорите о единой валюте, а как насчет остальных? Некоторое количество оценивается с 6 десятичными, поэтому вы не можете просто *100. Пожалуйста, у вас есть точка здесь, но вы могли бы быть более точным :)
AxelH

9
@AxelH За исключением середин финансовых расчетов, где могут существовать дробные центы, деньги всегда дискретны. Вы бы использовали один целочисленный тип для хранения данных. Таким образом, $ 5,34 будет храниться как 534. Долларовая часть равна val / 100 в целочисленной математике, а центы равны val% 100 в целочисленной математике, где% относится к оставшейся операции. Для денег с большим количеством знаков после запятой они все равно должны храниться как целые, потому что они дискретны. Даже если это не дискретно, чаще всего вам захочется откатиться на дискретное хранилище большую часть времени, потому что оно точное, поэтому вы не потеряете деньги на ошибки округления.
Трикси Вольф

72

Поплавок дает вам ок. Точность 6-7 десятичных цифр, в то время как двойная дает вам ок. 15-16. Также диапазон чисел больше для двойника.

Для двойного пространства требуется 8 байт, а для поплавка - всего 4 байта.


13

Числа с плавающей точкой, также известные как действительные числа, используются при оценке выражений, которые требуют дробной точности. Например, вычисления, такие как квадратный корень, или трансцендентные, такие как синус и косинус, приводят к значению, точность которого требует типа с плавающей точкой. Java реализует стандартный (IEEE – 754) набор типов и операторов с плавающей точкой. Существует два вида типов с плавающей запятой, с плавающей точкой и двойной, которые представляют числа одинарной и двойной точности соответственно. Их ширина и диапазоны показаны здесь:


   Name     Width in Bits   Range 
    double  64              1 .7e308 to 1.7e+308
    float   32              3 .4e038 to 3.4e+038


поплавок

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

Вот несколько примеров объявлений переменных с плавающей точкой:

float hightemp, lowtemp;


двойной

Двойная точность, обозначаемая ключевым словом double, использует 64 бита для хранения значения. Двойная точность на самом деле быстрее, чем одинарная точность на некоторых современных процессорах, оптимизированных для высокоскоростных математических вычислений. Все трансцендентные математические функции, такие как sin (), cos () и sqrt (), возвращают двойные значения. Когда вам необходимо поддерживать точность в течение многих итеративных вычислений или манипулировать большими числами, двойным является лучший выбор.


Этот ответ ясно прояснил, когда нам следует использовать float и double. Почему нет?
Вы выиграли

8
Ни Java, floatни doubleтипы лучше не использовать для валюты в Java, поскольку они открывают возможность для округления ошибок. В этой статье более подробно: javapractices.com/topic/TopicAction.do?Id=13
PPartisan

1
«float может быть полезен при представлении долларов и центов». - нет, нет, нет, неононо. Никогда, никогда не храните валюту как плавающие / двойные.
снижение активности

2

Тем не менее, Java имеет тенденцию к использованию double для вычислений:

Например, в программе, которую я написал ранее сегодня, методы не работали, когда я использовал float, но теперь отлично работают, когда я заменил float на double (в IDE NetBeans):

package palettedos;
import java.util.*;

class Palettedos{
    private static Scanner Z = new Scanner(System.in);
    public static final double pi = 3.142;

    public static void main(String[]args){
        Palettedos A = new Palettedos();
        System.out.println("Enter the base and height of the triangle respectively");
        int base = Z.nextInt();
        int height = Z.nextInt();
        System.out.println("Enter the radius of the circle");
        int radius = Z.nextInt();
        System.out.println("Enter the length of the square");
        long length = Z.nextInt();
        double tArea = A.calculateArea(base, height);
        double cArea = A.calculateArea(radius);
        long sqArea = A.calculateArea(length);
        System.out.println("The area of the triangle is\t" + tArea);
        System.out.println("The area of the circle is\t" + cArea);
        System.out.println("The area of the square is\t" + sqArea);
    }

    double calculateArea(int base, int height){
        double triArea = 0.5*base*height;
        return triArea;
    }

    double calculateArea(int radius){
        double circArea = pi*radius*radius;
        return circArea;
    }

    long calculateArea(long length){
        long squaArea = length*length;
        return squaArea;
    }
}

У меня была такая же проблема сегодня. В чем может быть причина этого смещения?
Шати

2

Это даст ошибку:

public class MyClass {
    public static void main(String args[]) {
        float a = 0.5;
    }
}

/MyClass.java:3: ошибка: несовместимые типы: возможное преобразование с потерями от двойного к плавающему с плавающей точкой a = 0,5;

Это будет работать отлично

public class MyClass {
    public static void main(String args[]) {
        double a = 0.5;
    }
}

Это также будет отлично работать

public class MyClass {
    public static void main(String args[]) {
        float a = (float)0.5;
    }
}

Причина : Java по умолчанию хранит действительные числа как двойные, чтобы обеспечить более высокую точность.

Double занимает больше места, но более точно во время вычислений, а float занимает меньше места, но менее точно.


1

Согласно стандартам IEEE, float - это 32-битное представление действительного числа, а double - 64-битное представление.

В программах Java мы обычно видим использование двойного типа данных. Это просто для того, чтобы избежать переполнения, поскольку диапазон чисел, который может быть размещен с использованием типа данных double, больше, чем диапазон, когда используется float.

Также, когда требуется высокая точность, рекомендуется использовать double. Немногие библиотечные методы, которые были реализованы давным-давно, по-прежнему требуют использования типа данных float как обязательного (это только потому, что он был реализован с использованием float, больше ничего!).

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


0

Этот пример иллюстрирует, как извлечь знак (крайний левый бит), показатель степени (8 следующих битов) и мантиссу (23 крайних правых бита) из числа с плавающей запятой в Java.

int bits = Float.floatToIntBits(-0.005f);
int sign = bits >>> 31;
int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
int mantissa = bits & ((1 << 23) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa));

Тот же подход может быть использован для двойных (11-битная экспонента и 52-битная мантисса).

long bits = Double.doubleToLongBits(-0.005);
long sign = bits >>> 63;
long exp = (bits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1);
long mantissa = bits & ((1L << 52) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Double.longBitsToDouble((sign << 63) | (exp + ((1 << 10) - 1)) << 52 | mantissa));

Кредит: http://sj.github.io/java-float/


0

Вы должны использовать double вместо float для точных вычислений и float вместо double при использовании менее точных вычислений. Float содержит только десятичные числа, но double содержит число с плавающей точкой двойной точности IEEE754, что упрощает более точное хранение и вычисление чисел. Надеюсь это поможет.


0

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

  • Если мы хотим использовать число с плавающей запятой в качестве типа данных с плавающей запятой, то вызывающий метод должен явно суффикс F или f, потому что по умолчанию каждое число с плавающей запятой обрабатывается как double. Это увеличивает нагрузку на программиста. Если мы используем число с плавающей точкой в ​​качестве двойного типа данных, нам не нужно добавлять суффикс.
  • Float - это тип данных с одинарной точностью, то есть он занимает 4 байта. Следовательно, в больших вычислениях мы не получим полный результат. Если мы выберем двойной тип данных, он займет 8 байтов, и мы получим полные результаты.

Типы данных с плавающей запятой и двойной тип данных были разработаны специально для научных расчетов, где допустимы ошибки аппроксимации. Если точность является наиболее приоритетной задачей, то рекомендуется использовать класс BigDecimal вместо типов данных с плавающей запятой или типа double. Источник: - Float и двойные типы данных в Java

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.