masay
masay

Reputation: 933

double scientific notation to decimal notation in java

I am trying to convert scientific double to decimal double in java. I am sending a value from server (coded on C++) which is running on X86 (little endian) machine and I was using htonl, ntohl methods for convertion before sending data to client (coded on java). But now, I have to sent this value with no conversion like LE to BE. The coversion is being done on client (java) side. Other type can be converted correctly but for double, this is not present. When client receive a double type, this value can not be read correctly. Here is my java code for double conversion.

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

After all of these steps, I got 9.534475227E-315 if I sent 0.3 from server.
Thanks and regards.

Upvotes: 1

Views: 6204

Answers (6)

High Performance Mark
High Performance Mark

Reputation: 78316

If you sent 0.3 from server to client and got back 9.534475227E-315 the last thing you ought to do is convert that value to 0.3 again. The returned value is very close to 0 in f-p terms, and indicates some error in the sending and returning process.

I am puzzled at your question, I did not know that Java implemented a Decimal class but then my Java knowledge is old and scant. Do you perhaps mean a BigDecimal ? Or are you converting string formats of floating-point numbers, which would be a completely different kettle of fish?

Upvotes: 0

masay
masay

Reputation: 933

I solved the my question and thank to you all for your helps. Much appreciated. So here is the solution.

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

When I send a data from server in little endian format, I can convert incoming little endian formatted value to big endian formatted value with this code in java.

Upvotes: 0

finnw
finnw

Reputation: 48619

Don't roll your own bit twiddling like that. It's in the standard API. See 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);
}

Upvotes: 1

gary
gary

Reputation: 584

Your use of the term "scientific notation" sorta suggests you are dealing with text data that looks like "3.0e-1". But I think I understand.

It seems like the problem is just reading binary data written in a non-java word order. Yet why are the integers written big-endian, yet the doubles written little-endian? And why are you reading in such a strange manner? Doesn't your compiler complain about the 'int'? It may have been hiding a problem. (EDIT: my error - I was stuck on 64 bits for the double)

It would be useful for everyone to see a hex dump of your data. Are the bytes flipped, or just the words?

Maybe this code will provide some inspiration. Please excuse the 'get-r-done' use of variables.

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

Upvotes: 1

Yoni
Yoni

Reputation: 10321

It sounds like you are reading the value wrong from the client, but in any case, NumberFormat is your friend :) http://java.sun.com/j2se/1.5.0/docs/api/index.html?java/text/NumberFormat.html

EDIT: considering the code sample that you posted, I have to agree with @trashgod that your conversion code is flawed. Perhap DataInputStream can assist -> http://java.sun.com/javase/6/docs/api/java/io/DataInputStream.html

Upvotes: 3

trashgod
trashgod

Reputation: 205785

Your conversion is flawed in several ways, including the use of signed arithmetic and incorrect bit values. You might study the format and look at the approach shown in this glossary entry.

Upvotes: 1

Related Questions