Solved

Java failing to multiply two numbers correctly!

Posted on 2004-08-17
18
845 Views
Last Modified: 2008-03-17
Hi,
I was wondeing if anyone could help clear up some very strange java behaviour.  I have been running a program sucessfully for the last few weeks.  Recently it stoped working and I located the problem to the function below.  For some reason the program has started to assign a completely wrong negative number when it multiplies two values input to the function.  An example  from the print statement below is 171944*172557=-3946302646.  If anyone has any ideas as to what could be causing the problem it would be greatly appreciated.
        Cheers,
        everton690.


private static void writeList(int size, int pageno,int linkno) {
            
 try {
      
        File f = new File("somefile");
        RandomAccessFile raf = new RandomAccessFile(f, "rw");
 
System.out.println(pageno+"*"+size+"="+(pageno*size));

       int location=(pageno*size)+linkno;
           
   raf.seek(location);
    raf.writeByte(1);
 
   
    } catch (IOException e) {
          System.out.println("exception");
    }
                      
             
}
0
Comment
Question by:everton690
  • 5
  • 4
  • 3
  • +4
18 Comments
 
LVL 7

Accepted Solution

by:
bvanderveen earned 175 total points
ID: 11820746
I think you are using a datatype that is too small.  When that happens, your result gets screwy.  Try using the long datatype for the result.
0
 
LVL 7

Expert Comment

by:bvanderveen
ID: 11820775
To be clear, int is 32 bits, or a max upper limit of 4,294,967,295.  The negative number is from "overflow" resetting the sign bit. Java doesn't throw an error when this happens, so you need to make sure you have an adequate datatype.   A long (integer) datatype is 64 bits, with an upper limit of 18,446,744,073,709,551,615, which gives a bit more range.
0
 

Author Comment

by:everton690
ID: 11820812
Ints work fine, I tried using longs instead just in case but this made no difference unfortunately!
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 5

Expert Comment

by:TrekkyLeaper
ID: 11820873
I just tried with a long and it worked fine. Try replacing:

(pageno*size)

with:

((long)pageno * (long)size)
0
 
LVL 35

Assisted Solution

by:girionis
girionis earned 75 total points
ID: 11820888
bvanderveen is right, you do not use the proper data types that's why it's failing. Multiplying those two int values will result in a long. Try this:

long pageno = 171944;
                   long size = 172557;
                 System.out.println(pageno+"*"+size+"="+(pageno*size));

and you wil lsee the correct result. Now try this:

int pageno = 171944;
                   int size = 172557;
                 System.out.println(pageno+"*"+size+"="+(pageno*size));

and you will see the wrong result.
0
 
LVL 7

Expert Comment

by:bvanderveen
ID: 11820917
It is defaulting your result to an int.  Make it explicit with a cast or by declaring a variable for the result

   long result;
   int pageno = 171944;
   int size = 172557;
   result = pageno * size;
  System.out.println(pageno+"*"+size+"="+ result);
0
 

Author Comment

by:everton690
ID: 11820919
This does not help in my case, maybe the solution lies elsewhere.  The program had been working fine with ints for a few weeks
0
 
LVL 35

Expert Comment

by:girionis
ID: 11820944
> This does not help in my case, maybe the solution lies elsewhere.  The program had been working fine with ints for a few weeks

This could be because you were passing it values that their product didn't exceed the int limit.
0
 
LVL 35

Expert Comment

by:girionis
ID: 11820955
What's wrong with making them long? Is it the memory you want to save?
0
 
LVL 7

Expert Comment

by:bvanderveen
ID: 11821362
It is almost certainly an overflow.  The giveaway is the sign changing to negative.  The overflow is setting the sign bit.  

It worked before because you didn't overflow.  Don't believe us?   Step through with a debugger, and check the values you are multiplying.  If they exceed (2**32) -1 you are going to overflow every time.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11821543
>>To be clear, int is 32 bits, or a max upper limit of 4,294,967,295

Not so, the max is 2,147,483,648 as the datatype is signed

But you're right about the overflow:

171944*172557 = 29,670,140,808  i.e. a clear overflow
0
 
LVL 7

Expert Comment

by:bvanderveen
ID: 11821811
>>Not so, the max is 2,147,483,648 as the datatype is signed

Yep, forgot the sign bit.  

Upper limit for a long would be 9,223,372,036,854,775,808.  Ought to be big enough.

We have suggested casting the result to long.  I'm not sure this will work, if done after overflow has occured.  Compiler may make result an int when you multiply 2 ints together, then cast.  If still getting errors, make them all longs and see what happens.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11824308
Just make the parameters to the method long
0
 
LVL 24

Expert Comment

by:sciuriware
ID: 11824726
And where does the error come from? From the fact that JAVA only promotes int's to long's if requested:

long q = 1000000000 * 1000000000; // Fails because you introduce integers.
long q = 1000000000L * 1000000000; // Succeeds, because you force the second integer into promotion to long.

A common error is:

public static final long TERA = 1024*1024*1024*1024;  // Without any warning a **** constant is created.

;JOOP!
0
 
LVL 92

Expert Comment

by:objects
ID: 11826455
> Just make the parameters to the method long

Not necessary as earlier mentioned.

Try this if you haven't already:

 long location=((long)pageno*(long)size)+(long)linkno;
0
 

Author Comment

by:everton690
ID: 11828576
Cheers,
Bvanderveen you were right all along it was just a simple overflow problem, I had been expecting something more drastic.  The reason I never had the problem before was because the int values were smaller (bit of a schoolboy error).  Thanks again.
         everton690.
 
0
 
LVL 35

Expert Comment

by:girionis
ID: 11828667
:)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11829578
>>Not necessary as earlier mentioned.

How do you know? One or more of the parameters may already be too big for a int
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
jdbc error in jsp application 20 63
eclipse buid path vs tomcat lib path 10 34
How  can  i  resolve  HTTP Status 404 -? 8 42
jsp error 6 25
An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question