?
Solved

Java failing to multiply two numbers correctly!

Posted on 2004-08-17
18
Medium Priority
?
849 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +4
18 Comments
 
LVL 7

Accepted Solution

by:
bvanderveen earned 700 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
Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

 
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 300 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

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

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

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…
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
The viewer will learn how to implement Singleton Design Pattern in Java.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Suggested Courses
Course of the Month11 days, 22 hours left to enroll

752 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