Recent

Author Topic: Range check error?  (Read 27355 times)

jacobite

  • New Member
  • *
  • Posts: 10
Range check error?
« on: November 06, 2013, 01:12:41 pm »
This code which calculates the value of Pi works ok at 10000 iterations:

Code: [Select]
program find_pi;
var
  x, y: real;
  i, inside: integer;
begin
  randomize;
  inside:= 0;
  for i:= 1 to 10000 do begin
    x:= random; y:= random;
    // is the point inside the circle?
    if (sqr(x - 0.5) + sqr(y - 0.5)) <= sqr(0.5) then
      inc(inside)
  end;
  // calculate proportion of hits
  writeln('Pi = ', 4*inside/i);
  readln
end.     

But when I increase the number to 100000 I get the following error:

Quote
Error:range check error while evaluating constants
« Last Edit: November 06, 2013, 01:45:15 pm by jacobite »

jacobite

  • New Member
  • *
  • Posts: 10
Re: Range check error?
« Reply #1 on: November 06, 2013, 03:28:21 pm »
Ok, I figured it out. If I replace 'integer' by 'longint' I don't get the error.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Range check error?
« Reply #2 on: November 06, 2013, 03:40:13 pm »
Also note that the Random function returns an extended result.
So x and y may well overflow (or not be pseudo-random) since they are declared as real (which is platform-dependent, but smaller than extended).

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Range check error?
« Reply #3 on: November 06, 2013, 04:49:10 pm »
In the default {$mode fpc}, integer maps to smallint, which is 16-bit signed integer. Please see the documentation for reference.

CM630

  • Hero Member
  • *****
  • Posts: 1696
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Range check error?
« Reply #4 on: February 02, 2015, 02:07:13 pm »
I got the same problem, I get Error: range check error while evaluating constants when trying to run this code, no matter if I use Integer or LongInt. I also tried to replace {$mode objfpc}{$H+} with {$mode delphi}{$H+}, but it solved nothing.

Code: [Select]
function DAQmxErrorDescription (ErrorCode: LongInt): String;
begin
  case ErrorCode of
     $00000000: Result:='DAQmxSuccess';
     $FFFCCC73: Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';
     $FFFCCC75: Result:='ErrorWaitForNextSampClkDetected3OrMoreSampClks';
...
     else
         Result:='Unknown error';
  end;
     


Could the reason be, that CASE cannot be used with greater integers?
If so, should I report it as bug in Lazarus or rather FPC?
« Last Edit: February 02, 2015, 02:19:53 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

rvk

  • Hero Member
  • *****
  • Posts: 7043
Re: Range check error?
« Reply #5 on: February 02, 2015, 02:30:32 pm »
Are you getting an "Error: range check.....". Weird.
I'm getting an "Warning: range check error while evaluating constants (4294757491 must be between -2147483648 and 2147483647)"

Reason is your ErrorCode is a LongInt which is a signed 32bit value and is in the range: -2147483648 and 2147483647.
Your $FFFCCC73 is higher.

What you want is a unsigned 32 bit value: Cardinal.
So change the LongInt in a Cardinal and you won't get an error.
(you'll need to do this everywhere you call this routine too)

balazsszekely

  • Guest
Re: Range check error?
« Reply #6 on: February 02, 2015, 02:32:40 pm »
Lazarus case keyword supports all ordinal types except boolean. The biggest is LongWord(QWord and int64 are not ordinal type).
Conclusion:
The largest number you can use with case is 4294967295.
Code: [Select]
function DAQmxErrorDescription (ErrorCode: LongWord): String;
begin
  case ErrorCode of
     $00000000: Result:='DAQmxSuccess'; //OK
     $FFFCCC73: Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';   //OK
     $FFFCCC75: Result:='ErrorWaitForNextSampClkDetected3OrMoreSampClks';  //OK
     else
         Result:='Unknown error';
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ErrorCode: LongWord;
begin
  ErrorCode := $FFFCCC75;
  ShowMessage(DAQmxErrorDescription(ErrorCode));
end;


Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Range check error?
« Reply #7 on: February 02, 2015, 05:55:38 pm »
Are you getting an "Error: range check.....". Weird.
I'm getting an "Warning: range check error while evaluating constants (4294757491 must be between -2147483648 and 2147483647)"
When range checking is activated, it's an error. Otherwise, it's a warning. In other words, range checking is always performed.
Lazarus case keyword supports all ordinal types except boolean
Excuse me?
Code: [Select]
begin
  case 1 <> 0 of
     false: ;
     true: ;
  end;
end.
Seems to compile fine.

balazsszekely

  • Guest
Re: Range check error?
« Reply #8 on: February 02, 2015, 06:36:27 pm »
@Leledumbo
Yes, apparently it does supports boolean, which is good. According to the lazarus help it's not supported though!
« Last Edit: February 02, 2015, 06:38:37 pm by GetMem »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Range check error?
« Reply #9 on: February 03, 2015, 02:11:17 am »
@Leledumbo
Yes, apparently it does supports boolean, which is good. According to the lazarus help it's not supported though!
Which one? Please report if it's in the official documentation, and please correct if it's in the wiki.

CM630

  • Hero Member
  • *****
  • Posts: 1696
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Range check error?
« Reply #10 on: February 03, 2015, 08:00:19 am »
Are you getting an "Error: range check.....". Weird.
I'm getting an "Warning: range check error while evaluating constants (4294757491 must be between -2147483648 and 2147483647)"

Reason is your ErrorCode is a LongInt which is a signed 32bit value and is in the range: -2147483648 and 2147483647.
Your $FFFCCC73 is higher.

What you want is a unsigned 32 bit value: Cardinal.
So change the LongInt in a Cardinal and you won't get an error.
(you'll need to do this everywhere you call this routine too)
So, when I changed LongInt to Cardinal I stopped having errors in the function itself. Which lead to other problems.
Because numbers are actually 32 bit long integers, i.e. LongInts (according Lazarus wiki: A longint is 4 bytes long.).
For example FFFCF273= -200077;  FFFCF272= 200078; FF FF FF FF = -1; 80000000= -2 147 483 648.
Actually the reason of my seems to be that FPC considers my signed longint to be unsigned.
Is there a way to tell FPC to consider my $FFFCF273 to a signed longingt, or I should do all the conversion trough strings?

Here is a functions that works, but could there be an autocasting solution?
Code: [Select]
function DAQmxErrorDescription (ErrorCode: LongInt): String;
begin
  case ErrorCode of
     LongInt($00000000): Result:='DAQmxSuccess';
     LongInt($FFFCCC73): Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';
..

« Last Edit: February 03, 2015, 08:20:18 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

rvk

  • Hero Member
  • *****
  • Posts: 7043
Re: Range check error?
« Reply #11 on: February 03, 2015, 09:27:35 am »
Which lead to other problems.
I already stated that you need to look at the routines where you call this function. In all those places you need to replace LongInt with Cardinal (or LongWord) too.

Actually the reason of my seems to be that FPC considers my signed longint to be unsigned.
Where does FPC consider your LongInt to be unsigned? You are trying to compare your LongInt to a value which can never be in a LongInt. If you're comparing a variable to values like $FFFCCC73 you should make sure your variable itself is a unsigned long integer too (and not a signed long integer like you're using now).

Where in your program are you assigning this value $FFFCCC73 ??? Is this coming from a function you made or an existing function? Look at the definition of that function. You see it defines the result as LongWord or Cardinal and not as LongInt because it can't put $FFFCCC73 in a LongInt without getting a rangecheck error there too.

You could use LongInt($FFFCCC73) in your case-statement but I wouldn't recommend it. It's not how it's supposed to work.

So look everywhere in your program where you are getting this errorcode back from some function and change the variable of that errorcode to a Cardinal or LongWord (or whatever is defined by that function). After that also change the LongInt in your function to Cardinal or LongWord and now your using the unsigned 32bit everywhere (without getting any range check errors).

B.T.W. if the function where the errorcode comes from defines that if a negative error is returned it is an error then an signed long integer is the correct variable. But in that case you shouldn't compare it to an unsigned value like $FFFCCC73.

In that case you could do the following:
Code: [Select]
function DAQmxErrorDescription (ErrorCode: LongInt): String;
begin
  case ErrorCode of
     0: Result:='DAQmxSuccess';
     -209805: Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';
..
I noticed this page stated for example DAQmxWriteDigitalU32-function returns a signed long integer:
Quote
The error code returned by the function in the event of an error or warning. A value of 0 indicates success. A positive value indicates a warning. A negative value indicates an error.
So you would have to check for negative values and not positive values like you do now. (That's assuming your error comes from one of these functions)
« Last Edit: February 03, 2015, 09:38:55 am by rvk »

CM630

  • Hero Member
  • *****
  • Posts: 1696
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Range check error?
« Reply #12 on: February 03, 2015, 09:58:46 am »
Which lead to other problems.
I already stated that you need to look at the routines where you call this function. In all those places you need to replace LongInt with Cardinal (or LongWord) too.
 

No, my numbers are signed, so I cannot and must not use Cardinal/ LongWord values.  These codes are from national Instrumens libraries, and if one tries googling them as Cardinal values,  he won't find them.
Actually the reason of my seems to be that FPC considers my signed longint to be unsigned.
The zero (leftmost) bit of $FFFCCC73 is 1, which means that the number is negative. But when I use CASE OF $FFFCCC73 Pascal considers  $FFFCCC73 to be an unsigned number, hence the problem occurs. I am not sure if this is bug in FPC, since ErrorCode is defined as a LongInt or its is expected, that $XYZ... numbers are always converted to Cardinal.
So I see no problem in LongInt( $XYZ... ), but I would use a simpler way, if it exists.
 

Code: [Select]

function DAQmxErrorDescription (ErrorCode: LongInt): String;
begin
  case ErrorCode of
     0: Result:='DAQmxSuccess';
     -209805: Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';
..
Yes, but I would have to convert all $XYZ... to integers in the source code, while the other solution took about a minute with Find and Replace ;)
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Range check error?
« Reply #13 on: February 03, 2015, 10:05:00 am »
If you have to keep ErrorCode of type LongInt and using hex numbers in your case statement then you can use another unsigned variable to refer to the same memory occupied by ErrorCode using absolute:
Code: [Select]
function DAQmxErrorDescription (ErrorCode: LongInt): String;
var
  uErrorCode: DWord absolute ErrorCode;  //<----
begin
  case uErrorCode of  //<---
     $00000000: Result:='DAQmxSuccess';
     $FFFCCC73: Result:='ErrorCOCannotKeepUpInHWTimedSinglePoint';
...

Notice that you will have a problem with this code if you decided to compile for 64bit target because -209805 (which is $FFFCCC73 on 32bit target) becomes $FFFFFFFFFFFCCC73.
« Last Edit: February 03, 2015, 10:15:42 am by engkin »

rvk

  • Hero Member
  • *****
  • Posts: 7043
Re: Range check error?
« Reply #14 on: February 03, 2015, 10:28:09 am »
So, ok, you are dealing with the DAQmx... functions I found. These indeed state that the result is a signed long integer. In that case I'm puzzled where the value $FFFCCC73 comes from. $FFFCCC73 is a positive number (unless you cast it to a LongInt like you did in your last case-solution). I still think it's weird the National Instrumens libraries state the result is a signed long integer but your comparing them to positive numbers (like $FFFCCC73).

This is not a "bug" in FPC. $FFFCCC73 is just like it looks like... a positive number. I'm not aware of a simple automatic solution that FPC would consider $FFFCCC73 as a negative number (because it just isn't negative).

There are 4 possible solution you could use. (Edit: 5 with the one engkin provided above)
  • Convert the $FFFCCC73 numbers to real signed long integers (like -209805) like the National Instrumens libraries stated they are. This is probably the way it should be but I'm not sure if you have a list from the library stating those $FFFFxxxx numbers.
  • Use a cast around the errornumbers (with LongInt($FFFCCC73)) like you did in your last post. That way the high errornumbers are converted to negative numbers so you could compare them correctly to a LongInt. This is probably the next best thing because the numbers are turned negative with LongInt() and you're comparing them correctly
  • Use a cast around the variable ErrorCode. (Like "case Cardinal(ErrorCode) of"). The ErrorCode will become a positive value which you can compare.
  • You could temporarily disable the range check error. (but your still comparing unsigned with signed variables which isn't good)

B.T.W. does the function DAQmxGetErrorString not give you the same results as your own function?

Edit2: I found a list here and here. You'll see that the library uses real negative numbers (and not numbers like $FFFCCC73):
Code: [Select]
#define DAQmxErrorWriteNotCompleteBeforeSampClk                                    (-209801)
#define DAQmxErrorReadNotCompleteBeforeSampClk                                     (-209800)
#define DAQmxErrorDAQmxCantUseStringDueToUnknownChar                               (-200811)
#define DAQmxErrorDAQmxCantRetrieveStringDueToUnknownChar                          (-200810)
#define DAQmxErrorClearTEDSNotSupportedOnRT                                        (-200809)
#define DAQmxErrorCfgTEDSNotSupportedOnRT                                          (-200808)
#define DAQmxErrorProgFilterClkCfgdToDifferentMinPulseWidthBySameTask1PerDev       (-200807)
#define DAQmxErrorProgFilterClkCfgdToDifferentMinPulseWidthByAnotherTask1PerDev    (-200806)
#define DAQmxErrorNoLastExtCalDateTimeLastExtCalNotDAQmx                           (-200804)
#define DAQmxErrorCannotWriteNotStartedAutoStartFalseNotOnDemandHWTimedSglPt       (-200803)
#define DAQmxErrorCannotWriteNotStartedAutoStartFalseNotOnDemandBufSizeZero        (-200802)
....
You can find them all in NIDAQmx.h.
« Last Edit: February 03, 2015, 10:40:00 am by rvk »

 

TinyPortal © 2005-2018