Jump to content

Using "boolean" (integer [1|0]) return type in logical operation results in Math Error?


You are about to reply to a thread that has been inactive for 70 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I am trying to use the boolean (which I guess we have to use in ineger types?) return of a function in a logical operation (if A and B)
I'm getting a Math Error now.

The script compiles fine in the editor "pre-flight", the error occurs when trying to run this function.

I'm still new to this SL Script FrankenLanguage, so I'm not sure where the problem is O_o
FWIW, I've tried using 1 and 0 as the return values. It looks like "TRUE" and "FALSE" are just constants representing 1 and 0 respectively, so I wouldn't expect that to be an issue.
Of course I started out trying to use "boolean" as the return type, but that gave me a syntax error.
 

integer beginsWith(string str, string substr){
    integer ss_length = llStringLength(substr);
    if(llGetSubString(str, 0, ss_length) == substr)
        return TRUE;
    return FALSE;
}

...

 if(ItemType == INVENTORY_SOUND && beginsWith(ItemName, "Radio: ")){}

How do I use a supposed-to-be boolean in a logical operation?

Link to comment
Share on other sites

Just now, Love Zhaoying said:

Isn't the only "math error" divide by zero? (Or is that a different message?)

Since zero is one of the return values of the function, that's what I'm thinking too.

I vaguely recall there being other math errors that can happen, but probably not relevant here.

Link to comment
Share on other sites

There's a string indexing error in the function, making it return FALSE unless the strings match exactly. That wouldn't cause a math error but dunno.

You're giving the substring length as the ending index to llGetSubString, but it returns the characters *inclusively* between the indices so it should be decremented. For example your beginsWith("abcd", "abc") would get string length 3 for the prefix, and would then compare llGetSubString("abcd", 0, 3) => "abcd" to "abc", failing every time unless the strings match exactly and the overflowing ending index compensates.

 For instance, check the string length being 0 before comparing (separate if clause to avoid the string function being evaluated if the string length is 0, I guess, LSL logical AND/OR aren't shortcutting so every part of the statement gets executed), and then use length-1 instead.

integer beginsWith(string str, string substr){
    integer ss_length = llStringLength(substr);
    if(!ss_length)
        return FALSE;
    if(llGetSubString(str, 0, ss_length-1) == substr)
        return TRUE;
    return FALSE;
}

 

Link to comment
Share on other sites

5 hours ago, Love Zhaoying said:

Isn't the only "math error" divide by zero?

modulus by 0 (and maybe also 1?) has bitten me a few times. You could argue it's divide by zero in disguise, but it's a good disguise to look for.

  • Like 2
Link to comment
Share on other sites

12 minutes ago, Quistess Alpha said:

You could argue it's divide by zero in disguise, but it's a good disguise to look for.

Completely useless tidbit but since I just read about it for unrelated reasons, on x86 (integer) modulus and divide are the same operation, you get the other one "for free" at the same time.

DIV (unsigned) and IDIV (signed) produce both the quotient in AL/AX/EAX/RAX and the remainder in AH/DX/EDX/RDX.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

12 hours ago, Frionil Fang said:

Completely useless tidbit but since I just read about it for unrelated reasons, on x86 (integer) modulus and divide are the same operation, you get the other one "for free" at the same time.

Even more completely useless expansion to that; it's actually very common on most architectures that offer division, because they both just fall out of the process, so you're throwing one away each time otherwise.  Even worse, unlike multiplication which is often single-cycle even on smaller modern processors, division is very often still multi-cycle on any but the largest (a single-cycle divider dwarfs a multiplier, which itself dwarfs an adder — the original largest component of an arithmetic unit).  That's why a lot of languages also offer some form of divmod command which captures both results in one go.  It's even more fun in something like risc-v, where you do only get one result (they do 3-register instructions, but not 4), but implementations (especially those which don't do single-cycle division) are specifically recommended to cache the result so a subsequent matching instruction can return the other, without having to re-do the (multi-cycle) division.

So yeah, it really, actually, literally is division in disguise.

  • Like 1
Link to comment
Share on other sites

On 3/7/2024 at 11:20 PM, Qie Niangao said:

(… also llSubStringIndex() might prove useful here'bouts.)

this ^^

breaking it down

integer beginswith(string str, string substr)
{
   return llSubStringIndex(str, substr) == 0;
   // return TRUE when str begins with substr, else return FALSE
}

// do it with the NOT operator
integer beginswith(string str, string substr)
{
   return !llSubStringIndex(str, substr);
   // returns TRUE when str begins with substr, else return FALSE
}

// inline it for efficiency
if ((ItemType == INVENTORY_SOUND) & !llSubStringIndex(ItemName, "Radio: "){}
    // TRUE & TRUE == TRUE

 

 

  • Like 1
Link to comment
Share on other sites

Hello everybody!

I've had a rough week, apologies for the late reply :/

Thank you so much for replying and providing information 🙌

On 3/7/2024 at 11:14 AM, Frionil Fang said:

There's a string indexing error in the function, making it return FALSE unless the strings match exactly. That wouldn't cause a math error but dunno.

You're giving the substring length as the ending index to llGetSubString, but it returns the characters *inclusively* between the indices so it should be decremented. For example your beginsWith("abcd", "abc") would get string length 3 for the prefix, and would then compare llGetSubString("abcd", 0, 3) => "abcd" to "abc", failing every time unless the strings match exactly and the overflowing ending index compensates.

 For instance, check the string length being 0 before comparing (separate if clause to avoid the string function being evaluated if the string length is 0, I guess, LSL logical AND/OR aren't shortcutting so every part of the statement gets executed), and then use length-1 instead.

integer beginsWith(string str, string substr){
    integer ss_length = llStringLength(substr);
    if(!ss_length)
        return FALSE;
    if(llGetSubString(str, 0, ss_length-1) == substr)
        return TRUE;
    return FALSE;
}

 

Thank you!

Between the above and some moving things around, the math error disappeared.

On 3/7/2024 at 11:20 AM, Qie Niangao said:

Apparently LSO threw math errors for imaginary results of llPow() and llSqrt().

(… also llSubStringIndex() might prove useful here'bouts.)

 

6 hours ago, elleevelyn said:

this ^^

breaking it down

integer beginswith(string str, string substr)
{
   return llSubStringIndex(str, substr) == 0;
   // return TRUE when str begins with substr, else return FALSE
}

// do it with the NOT operator
integer beginswith(string str, string substr)
{
   return !llSubStringIndex(str, substr);
   // returns TRUE when str begins with substr, else return FALSE
}

// inline it for efficiency
if ((ItemType == INVENTORY_SOUND) & !llSubStringIndex(ItemName, "Radio: "){}
    // TRUE & TRUE == TRUE

Ooh, of course. Thank you!

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 70 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...