ChatGPT解决这个技术问题 Extra ChatGPT

Java中的浮点和双精度数据类型

float 数据类型是单精度 32 位 IEEE 754 浮点数,双精度数据类型是双精度 64 位 IEEE 754 浮点数。

这是什么意思?我什么时候应该使用 float 而不是 double 或反之亦然?

当内存使用至关重要时,您应该使用浮点数而不是双精度数。如果您需要更精确的计算,请使用双精度数。
@Everv0id:我不确定在任何情况下内存都如此紧张以至于不得不牺牲空间的准确性。 (你正在使用 Java,看在上帝的份上……)在某些情况下可能需要它,但在我的实践中,我很少看到它。如果您想详细说明为什么您认为这是一个好主意,那么提供一个带有 for-instance 的答案将是一个有价值的补充。
@Makoto 实际上,我从未使用过花车,只有双打。但是可能有一些应用程序(理论上)应该保留大量的浮点数,因此 2 倍的内存使用可能是至关重要的。理论上,ofc;实际上,您总是可以购买另一台服务器。
我使用了 4 字节甚至 2 字节的固定精度数字来节省内存,但除非你有数十亿个这样的数字,否则不太可能值得。您写“double”而不是“float”(它多了一个字母)所花费的时间比您使用的额外内存价值多 1000 倍,但如果使用 double 而不是 float 可以节省与精度相关的时间错误,值得。

M
Makoto

上面的 Wikipedia page 是一个很好的起点。

总结一下:

float 以 32 位表示,具有 1 个符号位、8 个指数位和 23 位有效数字(或从科学记数法数得出的数字:2.33728*1012;33728 是有效数字)。

double 用 64 位表示,有 1 个符号位、11 位指数和 52 位有效位。

默认情况下,Java 使用 double 来表示它的浮点数(因此将文字 3.14 输入为 double)。它也是可以为您提供更大数字范围的数据类型,因此我强烈建议在 float 上使用它。

可能有某些库实际上会强制您使用 float,但总的来说 - 除非您可以保证您的结果足够小以适合 floatprescribed range,否则最好选择 {4 }。

如果您需要准确性 - 例如,您不能有不准确的十进制值(如 1/10 + 2/10),或者您正在用货币做任何事情(例如,在系统中代表 $10.33 ),然后使用 BigDecimal,它可以支持任意数量的精度并优雅地处理这样的情况。


给定示例中不是 233728 == 尾数吗?我的意思是,整数部分还存储在哪里?
@mathguy54:在科学记数法中,2 是整数,0.33728 是尾数。 Here's a reference to that.
我正在搜索有关浮点数和双精度数的信息,发现了这一点并需要评论:如果您使用不涉及小数美分的货币做任何事情,那么使用 BigDecimal 是荒谬的。通用货币是离散数据,因此您应该使用整数数据类型。 (这是年轻程序员最常犯的错误之一——因为我们使用 . 来区分美元和美分,他们认为这是一个浮点值。事实并非如此。)
@TrixieWolf,您能否更具体一点,您是否建议使用两个整数(整数和小数部分)?你说的是通用货币,其余的呢?一些金额以小数点 6 进行评估,因此您不能简单地 *100。拜托,你有一个观点,但你能更准确吗:)
@AxelH除了可以存在小数美分的金融计算中间,货币总是离散的。您将使用一种整数类型来存储数据。所以 5.34 美元将存储为 534。美元部分在整数数学中是 val/100,美分在整数数学中是 val%100,其中 % 指的是余数运算。对于小数点后更多位的货币,它仍应存储为整数,因为它是离散的。即使它不是离散的,您通常也会希望在大多数情况下退回到离散存储,因为它是精确的,因此您不会因舍入错误而蒙受损失。
H
Henry

一个浮点数给你大约。 6-7 位小数精度,而双精度为您提供大约。 15-16。双倍的数字范围也更大。

double 需要 8 个字节的存储空间,而 float 只需要 4 个字节。


r
reducing activity

浮点数,也称为实数,用于计算需要小数精度的表达式。例如,诸如平方根之类的计算或诸如正弦和余弦之类的超越数会产生一个精度需要浮点类型的值。 Java 实现了标准 (IEEE–754) 浮点类型和运算符集。浮点类型有两种,float 和 double,分别代表单精度数和双精度数。它们的宽度和范围如下所示:

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

漂浮

float 类型指定使用 32 位存储的单精度值。单精度在某些处理器上更快,占用的空间是双精度的一半,但是当值非常大或非常小时时会变得不精确。当您需要小数部分但不需要很高的精度时,float 类型的变量很有用。

以下是一些示例浮点变量声明:

浮动高温,低温;

双倍的

双精度,由 double 关键字表示,使用 64 位来存储一个值。在一些针对高速数学计算进行了优化的现代处理器上,双精度实际上比单精度更快。所有超越数学函数,例如 sin()、cos() 和 sqrt(),都返回双精度值。当您需要在许多迭代计算中保持准确性,或者正在处理大数值时,double 是最佳选择。


这个答案清楚地阐明了我们何时应该使用 float 和 double。为什么不呢?
floatdouble 类型都不适用于 Java 中的货币,因为它们为舍入错误提供了机会。本文更详细地介绍:javapractices.com/topic/TopicAction.do?Id=13
“浮点数在表示美元和美分时很有用。” - 不,不,不,非诺诺诺。永远不要将货币存储为浮点数/双精度数。
H
Himanshu Singh

这将给出错误:

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 以确保更高的精度。

Double 占用更多空间但在计算过程中更精确,而 float 占用更少空间但不太精确。


P
Peter Mortensen

尽管如此,Java 似乎还是倾向于使用 double 进行计算:

以我今天早些时候编写的程序为例,当我使用 float 时,这些方法不起作用,但现在当我用 double 替换 float 时效果很好(在 NetBeans IDE 中):

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;
    }
}

我今天遇到了同样的问题。这种偏见背后的原因是什么?
P
Peter Mortensen

根据 IEEE 标准,float 是实数的 32 位表示,而 double 是 64 位表示。

在 Java 程序中,我们通常会看到双精度数据类型的使用。这只是为了避免溢出,因为使用 double 数据类型可以容纳的数字范围大于使用 float 时的范围。

此外,当需要高精度时,鼓励使用双精度。很少有很久以前实现的库方法仍然需要使用 float 数据类型作为必须的(那只是因为它是使用 float 实现的,没有别的!)。

但是,如果您确定您的程序需要少量数字并且使用浮点数不会发生溢出,那么使用浮点数将大大提高您的空间复杂度,因为浮点数需要双倍所需的一半内存。


o
okrunner

这个例子说明了如何从 Java 中的浮点数中提取符号(最左边的位)、指数(后面的 8 位)和尾数(最右边的 23 位)。

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://s-j.github.io/java-float/


b
boi yeet

您应该使用 double 而不是 float 进行精确计算,并且在使用不太精确的计算时使用 float 而不是 double。 Float 只包含十进制数,而 double 包含一个 IEEE754 双精度浮点数,更容易包含和计算更准确的数字。希望这可以帮助。


R
Rocco Jerry

在常规编程计算中,我们不使用浮点数。如果我们确保结果范围在浮点数据类型的范围内,那么我们可以选择浮点数据类型来节省内存。通常,我们使用 double 有两个原因:-

如果我们想使用浮点数作为浮点数据类型,那么方法调用者必须显式添加 F 或 f 后缀,因为默认情况下每个浮点数都被视为双精度数。增加了程序员的负担。如果我们使用浮点数作为双精度数据类型,那么我们不需要添加任何后缀。

Float 是一种单精度数据类型,意味着它占用 4 个字节。因此,在大型计算中,我们不会得到完整的结果。如果我们选择double数据类型,它占用8个字节,我们会得到完整的结果。

float 和 double 数据类型都是专门为科学计算而设计的,其中近似误差是可以接受的。如果准确性是最优先考虑的问题,则建议使用 BigDecimal 类而不是 float 或 double 数据类型。来源:- Float and double datatypes in Java