了解 C# 和 Java 中的 IEEE-754 64 位定点表示

问题描述 投票:0回答:1

考虑以下 Java 代码:

public class Program {
    public static void main(String args[]) {
      double number = Double.MAX_VALUE;
      String formattedNumber = String.format("%f", number);
      System.out.println(formattedNumber);
    }
}

1797693134862315700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000.000000

考虑等效的 C# 代码:

public class Program
{
    public static void Main(string[] args)
    {
        double value = double.MaxValue;
        Console.WriteLine(value.ToString("F"));
    }
}

1797693134862315708145274237317043567980705675258449965989174768031572607800285387605895586327668781715404589535143824 642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551339423045832369032229481658085593 32123348274797826204144723168738177180919299881250404026184124858368.000

鉴于

Double
的最大值为1.7976931348623157E+308,据我所知,Java输出是正确的;即浮点值实际上代表一个整数,其中前 17 位数字是 17976931348623157,后面是 292 个零。

注意:在 C# 中将

double
转换为
BigInteger
会产生相同的结果:

BigInteger value = (BigInteger)double.MaxValue;
Console.WriteLine(value);

1797693134862315708145274237317043567980705675258449965989174768031572607800285387605895586327668781715404589535143824 642343213268894641827684675467035375169860499105765512820762454900903893289440758685084551339423045832369032229481658085593 32123348274797826204144723168738177180919299881250404026184124858368

问题

  • 为什么这些值大相径庭,哪个应该被认为是正确的?
  • 如果 C# 实际上是不正确的,我将如何获得与 Java 产生的正确或相同的输出?
java c# double ieee-754
1个回答
0
投票

鉴于Double的最大值为1.7976931348623157E+308…

这是不正确的。

Double
使用的格式是 IEEE 754-2019 标准中指定的 binary64 或“双精度”格式。在这种格式中,有限数表示为±f•2e,其中f,表示的小数部分,是由二进制数字表示的数字,前一位数字(0或1)小数点及其后的 52 位和指数 e 是 [−1022, 1023] 中的整数。所以最大可表示的有限值是 +1.111111111111111111111111111111111111111111111111111112•21023,等于 +(21−2−52)•21023 = 21024−2971,其中正好是 179,769,313,486,231,570,814,527,423,731,704,356,798,070,567,525,844,996,598,917,476,803,157,260,780,028,538,760,589,558 ,632,766,878,171,540,458,953,514,382,464,234,321,326,889,464,182,768,467,546,703,537,516,986,049,910,576,551,282,076,245,49 0,090,389,328,944,075,868,508,455,133,942,304,583,236,903,222,948,165,808,559,332,123,348,274,797,826,204,144,723,168,738,1 77,180,919,299,881,250,404,026,184,124,858,368,所以 C# 输出是正确的。

Java 输出省略了有效数字并隐藏了真实值。这是因为 Java 规范规定,对于默认格式 “必须至少有一个数字来表示小数部分,除此之外,还有许多数字,但只是唯一区分参数值所需的数字”

double
类型的相邻值。”

© www.soinside.com 2019 - 2024. All rights reserved.