java中的十进制表示法的双重科学记数法

时间:2010-02-04 12:25:47

标签: java double

我正在尝试将java中的scientific double转换为decimal double。我从服务器(在C ++上编码)发送一个在X86(小端)机器上运行的值,我在使用htonl,ntohl方法进行转换之前将数据发送到客户端(在java上编码)。但现在,我必须发送此值而不像LE那样进行转换。转换是在客户端(java)端完成的。其他类型可以正确转换,但对于double,这不存在。当客户端收到double类型时,无法正确读取此值。这是我的双重转换的java代码。

protected int readInt(InputStream stream) throws IOException {
    int i0 = read(stream);
    int i1 = read(stream);
    int i2 = read(stream);
    int i3 = read(stream);
     int i=(i0 << 24) + (i1 << 16) + (i2 << 8) + (i3 << 0);
    return i;
}
protected double readDouble(InputStream stream) throws IOException {
    int i0 = readInt(stream);
    int i1 = readInt(stream);
    return Double.longBitsToDouble(((long)i0 << 32) + (i1 & 0xffffffffL));      
}

完成所有这些步骤后,如果我从服务器发送0.3,我得到了9.534475227E-315 谢谢和问候。

6 个答案:

答案 0 :(得分:3)

听起来你正在从客户端读错值,但无论如何,NumberFormat是你的朋友:) http://java.sun.com/j2se/1.5.0/docs/api/index.html?java/text/NumberFormat.html

编辑:考虑到您发布的代码示例,我必须同意@trashgod您的转换代码存在缺陷。 Perhap DataInputStream可以提供帮助 - &gt; http://java.sun.com/javase/6/docs/api/java/io/DataInputStream.html

答案 1 :(得分:1)

您的转换在几个方面存在缺陷,包括使用带符号的算术和不正确的位值。您可以研究format并查看此glossary条目中显示的方法。

答案 2 :(得分:1)

您使用术语“科学记数法”sorta表明您正在处理看起来像“3.0e-1”的文本数据。但我想我明白了。

似乎问题只是读取以非java字顺序编写的二进制数据。然而,为什么整数写成大端,但双打写的小端?你为什么这么奇怪地读书?你的编译器不抱怨'int'吗?它可能隐藏了一个问题。 (编辑:我的错误 - 我被困在64位的双倍)

每个人都可以看到数据的十六进制转储。字节是翻转的,还是单词?

也许这段代码会提供一些灵感。请原谅使用变量的'get-r-done'。

// convert CLI argument to double, write to file, and read back
// without args, default is "0.3"
// should try negative numbers!

import java.io.*;

public class BinaryFile {

    public static void main(String[] args) {

        String strFilePath = "WordFlippedDouble";
        boolean WRITEOP = true;
        double d, dd = 0.3;
        long ddFlip;

        if(args.length > 0) {
            dd = Double.valueOf(args[0]);
        }
        System.out.println("Starting with " + dd + " looks like " + 
            Long.toHexString(Double.doubleToLongBits(dd)));

        if(WRITEOP) {
            ddFlip = Double.doubleToLongBits(dd);
            ddFlip = (ddFlip<<32) | ((ddFlip>>32) & 0xFFFFFFFFL);
            System.out.println("WRITE: (flipped) looks like   " + Long.toHexString(ddFlip));
            try {
                FileOutputStream fout = new FileOutputStream(strFilePath);
                DataOutputStream dout = new DataOutputStream(fout);
                dout.writeLong(ddFlip);
                dout.close();
            } catch (Exception e) {
                System.out.println("ERROR: " + e.getMessage());
            }
        }

        if(false) return;                // testing

        try {
            FileInputStream fin = new FileInputStream(strFilePath);
            DataInputStream din = new DataInputStream(fin);
            ddFlip = din.readLong();
            d = Double.longBitsToDouble((ddFlip<<32) | ((ddFlip>>32) & 0xFFFFFFFFL));                                                     
            System.out.println("READ:  " + Long.toHexString(ddFlip) + " converts to " + 
                d + " DIFF: " + (dd-d));
            din.close();
        } catch(FileNotFoundException e) { 
            System.out.println("FileNotFoundException : " + e);
        }
        catch(IOException e) {
            System.out.println("IOException : " + e);
        }
    }
}

答案 3 :(得分:1)

不要像那样翻滚自己的位。它在标准API中。请参阅java.nio.ByteBuffer

protected int readInt(InputStream stream) throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
    //buffer.order(ByteOrder.LITTLE_ENDIAN); // optional
    stream.read(buffer.array());
    return buffer.getInt(0);
}
protected double readDouble(InputStream stream) throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(Double.SIZE / Byte.SIZE);
    //buffer.order(ByteOrder.LITTLE_ENDIAN); // optional
    stream.read(buffer.array());
    return buffer.getDouble(0);
}

答案 4 :(得分:0)

如果您从服务器向客户端发送0.3并返回9.534475227E-315,那么您应该做的最后一件事就是将该值再次转换为0.3。 f-p术语中返回的值非常接近0,表示发送和返回过程中存在一些错误。

我对你的问题感到困惑,我不知道Java实现了一个Decimal类,但后来我的Java知识已经很老了。你或许是指BigDecimal吗?或者你正在转换浮点数的字符串格式,这将是一个完全不同的鱼?

答案 5 :(得分:0)

我解决了我的问题并感谢大家的帮助。非常感激。所以这是解决方案。

  protected double readDouble(InputStream stream) throws IOException {

    return Double.longBitsToDouble(((long) read(stream) & 0xff) 
                                 | ((long) (read(stream) & 0xff) << 8)
                                 | ((long) (read(stream) & 0xff) << 16)
                                 | ((long) (read(stream) & 0xff) << 24)
                                 | ((long) (read(stream) & 0xff) << 32)
                                 | ((long) (read(stream) & 0xff) << 40)
                                 | ((long) (read(stream) & 0xff) << 48)                     
                                 | ((long) (read(stream) & 0xff) << 56));  }

当我以小端格式从服务器发送数据时,我可以使用java中的代码将传入的小端格式化值转换为大端格式化值。