View unanswered posts | View active topics It is currently Sat Aug 23, 2014 9:25 am






Reply to topic  [ 12 posts ] 
Weird division problem, 100000/1500 = -20? Right... 
Author Message
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3192
Location: Rotterdam, The Netherlands
Post Weird division problem, 100000/1500 = -20? Right...
Hey guys,

Using the following code, I get two different results for essentially the same division:
Code:
task main() {
  int _foo = 1500;
  int _baz = 0;
  _foo = 100000 / _foo;
  _baz = 100000 / 1500;
  nxtDisplayClearTextLine(3);
  nxtDisplayString(3, "foo: %d", _foo);
  nxtDisplayClearTextLine(4);
  nxtDisplayString(4, "baz: %d", _baz);
  wait1Msec(10000);
}

My screen shows:
foo: -20
baz: 66

What gives? Can someone duplicate this? I am using RobotC 1.40 Public. I noticed it when I was trying to calculate the number of I2C reads I could do per second.

This is seriously odd. Ford, you're a mathematician; on what planet does 100000 / 1500 equal -20?

Regards,
Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Aug 28, 2008 12:03 pm
Profile WWW
Guru
User avatar

Joined: Sat Mar 01, 2008 12:52 pm
Posts: 1030
Post Re: Weird division problem, 100000/1500 = -20? Right...
mightor wrote:
Ford, you're a mathematician; on what planet does 100000 / 1500 equal -20?

Vroomvoodle 9 is famous for this.

_________________
regards,
HaWe aka Ford
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;task main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PutPixel(x,y);}}}while(1)}


Thu Aug 28, 2008 12:13 pm
Profile
Guru
User avatar

Joined: Sat Mar 01, 2008 12:52 pm
Posts: 1030
Post Re: Weird division problem, 100000/1500 = -20? Right...
Seriously:
I think it's an integer overflow error of a temp variable. :?
(maxInt=32655)
choose long instead of int and try it again 8)

Quote:
I think it's an integer overflow error of a temp variable. :?

... which actually MUST NOT happen!

_________________
regards,
HaWe aka Ford
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;task main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PutPixel(x,y);}}}while(1)}


Thu Aug 28, 2008 12:24 pm
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3192
Location: Rotterdam, The Netherlands
Post Re: Weird division problem, 100000/1500 = -20? Right...
Ford Prefect wrote:
Seriously:
I think it's an integer overflow error of a temp variable. :?
(maxInt=32655)
choose long instead of int and try it again 8)

Quote:
I think it's an integer overflow error of a temp variable. :?

... which actually MUST NOT happen!

It is odd because the last time I printed out a byte with nxtDisplayString() I was getting signed longs, which I then mistook for ints. I was convinced that on a 32bit platform ints would be 32 bit long, hehe. Oh well. My bad.

Regards,
Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Aug 28, 2008 2:39 pm
Profile WWW
Guru
User avatar

Joined: Sat Mar 01, 2008 12:52 pm
Posts: 1030
Post Re: Weird division problem, 100000/1500 = -20? Right...
so the problem is solved now by changing int to long?

_________________
regards,
HaWe aka Ford
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;task main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PutPixel(x,y);}}}while(1)}


Thu Aug 28, 2008 3:01 pm
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3192
Location: Rotterdam, The Netherlands
Post Re: Weird division problem, 100000/1500 = -20? Right...
Ford Prefect wrote:
so the problem is solved now by changing int to long?

Yeah, although it is weird that the the intermediate result is not cast to a long and then demoted back to an int. I will test this with gcc on my Linux VM. I will keep you posted!

Regards,
Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Aug 28, 2008 3:04 pm
Profile WWW
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3192
Location: Rotterdam, The Netherlands
Post Re: Weird division problem, 100000/1500 = -20? Right...
K, on Linux with glibc 2.7 an int is 4 bytes and a short is 2. I created this program. I used shorts because they're the same size as ints are on the NXT.
Code:
#include <stdio.h>

int main() {
  short _foo = 1500;
  short _baz = 0;
  _foo = 100000 / _foo;
  _baz = 100000 / 1500;
  printf("foo: %d\n", _foo);
  printf("baz: %d\n", _baz);
  return 0;
}

When ran it printed out 66 for both, as I expected RobotC to do. So with gcc the intermediate result *is* promoted and then demoted with some weirdness going on. So is this a bug with RobotC?

Regards,
Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Aug 28, 2008 3:19 pm
Profile WWW
Guru
User avatar

Joined: Sat Mar 01, 2008 12:52 pm
Posts: 1030
Post Re: Weird division problem, 100000/1500 = -20? Right...
I suppose this is working this way:
_foo = 100000 / _foo;

_foo is int,
so 1000000/_foo is passed to int:

_foo = int ((int)100000 / (int)_foo;)

It's a compiler fault, sure, this must not happen, but it happens!

I think a similar compiler fault causes my damned "-nan" at float calculations!!! Image

_________________
regards,
HaWe aka Ford
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;task main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PutPixel(x,y);}}}while(1)}


Thu Aug 28, 2008 3:22 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 614
Post Re: Weird division problem, 100000/1500 = -20? Right...
Quote:
I was convinced that on a 32bit platform ints would be 32 bit long, hehe. Oh well. My bad.

In C, the size of an "int" is independent of the hardware platform. "int" on ROBOTC are size 16 bits.

I've thought about changing the default for ROBOTC on NXT to an int size of 32 bits. Unfortunately this would have negative impacts. The ROBOTC VM (Virtual Machine) interpreter has many opcodes optimized for 16-bit ints and the compiled object files would be much larger because of use of the non-optimized formats. There are some long term enhancements to slowly remove this.

Another thing to be "cautious" of is that in C, non-float calculations are done, by default, at "int" precision unless one of the operands is a higher precision ("long"). So you could get 16-bit overflow in a calculation like:
Code:
longVariable = intVariable1 * intVariable2;

It is a bug for calculations involving long constants (i.e. outside of 16-bit range to be truncated to 16-bits. I will look into this.


Wed Sep 17, 2008 10:04 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 614
Post Re: Weird division problem, 100000/1500 = -20? Right...
Quote:
When ran it printed out 66 for both, as I expected RobotC to do. So with gcc the intermediate result *is* promoted and then demoted with some weirdness going on. So is this a bug with RobotC?

No, it is not a bug. On the PC, the intermediate calculations are done at 32-bits which is the size of an "int" on a PC.
In ROBOTC, intermediate calculations are done with 16-bit precison of "int" used by ROBOTC.


Wed Sep 17, 2008 10:14 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 614
Post Re: Weird division problem, 100000/1500 = -20? Right...
Code:
task main() {
  int _foo = 1500;
  int _baz = 0;
  _foo = 100000 / _foo;
  _baz = 100000 / 1500;
  nxtDisplayClearTextLine(3);
  nxtDisplayString(3, "foo: %d", _foo);
  nxtDisplayClearTextLine(4);
  nxtDisplayString(4, "baz: %d", _baz);
  wait1Msec(10000);
}

With ROBOTC 1.43 both "_foo" and "_baz" correctly print as value "66". I can't recall if something was fixed between 1.40 and 1.43 for this.

One minor thing to note if you look at the disassembly code (use F9 key). The compiler is smart enough to calculate the value of "_foo" at compile time.
int _foo = 1500;
int _baz = 0;
_foo = 100000 / _foo;
You'll see in the disassembly listing that there is no division and "_foo" is assigned a value of 66.
Code:
  int _foo = 1500;
  int _baz = 0;
  _foo = 100000 / _foo;
0012: 2B0342                   _foo = 66                         
  _baz = 100000 / 1500;
0015: 2B0442                   _baz = 66                         
  nxtDisplayClearTextLine(3);

I did some more testing by forcing the compiuler to generate the divide and it there is a bug where it is truncating 100000 to 16-bits and performing calculation at 16-bit precsion. THis is now fixed for the next ROBOTC release.


Wed Sep 17, 2008 10:49 pm
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3192
Location: Rotterdam, The Netherlands
Post Re: Weird division problem, 100000/1500 = -20? Right...
Dick,

Thanks for the explanations and insights into some of the inner workings of the compiler and VM :)

Regards,
Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Sep 18, 2008 2:08 am
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 12 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.