B4J Question How to do division of two Ints as integer division instead of floating point division?

emexes

Expert
Licensed User
B4X:
Dim Temp As Int = NewX * 2 + 1
Dim Temp1 As Int = Temp * SrcWidth
Dim Temp2 As Int = (NewWidth * 2)
Temp = Temp1 / Temp2

decompiles to:

Java:
int var23 = var21 * 2 + 1;
int var24 = var23 * var17;
int var25 = var1 * 2;
int var10000 = (int)((double)var24 / (double)var25);

Is there any way to get the castings out of the division line, without using inline Java?
 
Last edited:

MicroDrie

Well-Known Member
Licensed User
Dividing two integers returns an integer with any fractional part discarded resulting in a loss of precision. That loss of accuracy is limited in rule 4. If the loss of accuracy is not important to you, you can omit the casting and reduce it to honest dealing with loss of accuracy.

Division of two integers with loss of accuracy:
int a = 7;
int b = 3;
int result = a / b; // result will be 2
 
Upvote 0

emexes

Expert
Licensed User
Division of two integers with loss of accuracy:
int a = 7;
int b = 3;
int result = a / b; // result will be 2

But how do I do that on the BASIC side of B4J?

If I divide two integers in B4J and I look at the Java output, it shows that the two integers are being cast to Doubles before the division is done.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
I would use the number format to force rounding of the resulting number
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Is there any way to get the castings out of the division line, without using inline Java?
I don't know the answer but I guess it is not possible unless Erel changes B4X to Java conversion behavior.
The result will be the same with or without double casting so I think the real point here is whether integer division is faster than casting to double then do double division.
For old days without FPU or on MCU it impacts a lot but for modern PCs is it minimal?

It's nice to know that the integer division is first cast to double then cast to int which I don't know. ๐Ÿ‘
 
Upvote 0

emexes

Expert
Licensed User
Does it bother you just for performance or is it something else?

I was thinking performance, as in Java's fundamental type is 4-byte Int but Doubles are 8-bytes, plus the back-and-forth conversions between Int and Double.

But it's a bit hard to test if my thoughts are correct when it seems there is no way to do the divisions in integer rather than floating point.
 
Upvote 0

emexes

Expert
Licensed User
It's nice to know that the integer division is first cast to double then cast to int which I don't know.

The Int to Double cast is no problem: every conversion is exact, no rounding required.

Whereas the Double to Int cast usually involves rounding, which can bite if the rounding method you're expecting is different to what's happening.
 
Last edited:
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Whereas the Double to Int cast usually involves rounding, which can bite if the rounding method you're expecting is different to what's happening.
It is (int) so get integer towards zero other than floor(), ceil(), and round().

C/C++ cases:

20200720214253693.jpg
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
But how do I do that on the BASIC side of B4J?
What about a small in-line Java routine which gives you the full control of what you want?

It should be noted that calling the In-line Java routine also takes time. You therefore have to ask yourself whether it is worth using all kinds of tricks and a lot of time to achieve a possible very small speed gain.

Forty years ago we also squeezed everything as much as possible into the very limited memory space and it made sense to save time and memory space due to limited resources (like processor speed and memory space). Today you look more at the big picture, rapid development and testing. And yes, if something is really slow, you can always resort to programming a larger part of the program directly in Java.
 
Upvote 0

emexes

Expert
Licensed User
It is (int) so get integer towards zero other than floor(), ceil(), and round().
In plenty of other BASICs eg QuickBasic, PowerBasic, if you assign a floating point value to an integer variable, it gets rounded eg 1.6 becomes 2

Whereas C, and thus Java, and thus B4J, truncate.

Personally I prefer truncation, but for cases where it's important to get it right, I like to use conversion functions even better, so that there is no doubt about what should be happening. Yes I'm a nervous nelly, but that's because for most of my programming, small errors could rapidly explode into big problems.

Actually, on a related note, there was a floating-point error in the Patriot missile defence system that resulted in a missile being missed and (from memory) 18 people killed. The temporary workaround was to reboot the system every x hours but either that base forgot to do it or missed the memo.

 
Upvote 0

Alessandro71

Well-Known Member
Licensed User
Longtime User
I was thinking performance, as in Java's fundamental type is 4-byte Int but Doubles are 8-bytes, plus the back-and-forth conversions between Int and Double.

But it's a bit hard to test if my thoughts are correct when it seems there is no way to do the divisions in integer rather than floating point.
it matters only if you're performing millions of calculations, or else you're just losing your time
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Understood, and in this case it would be for:
A lot of things have already been covered in this post, except what exactly you want to do with the pixels. It would be useful to post a small example program so that we can see what you want and come up with a specific suggestion to speed things.
 
Upvote 0

emexes

Expert
Licensed User
what exactly you want to do with the pixels

The issue fell out of this thread:
Anyone know how to resize a image using "Nearest neighbor" method ?
where I think the results are being used for LED matrix displays, and I was thinking ahead to what if the routine was moved onto an Arduino, which typically don't have a FPU, or if it was used on larger images under real-time pressure.

come up with a specific suggestion to speed things.
I can see how to do it without any division or (I think) multiplication, and the need for such optimisation might never arise anyway, so... no need, but thank you anyway ๐Ÿป and tbh you're right: yes, I was avoiding describing the use-case, because it looked like you enjoy a good programming challenge as much as I do, and I felt it'd be better to save our enthusiasms for actual problems rather than prospective problems that might never happen. ๐ŸŽฏ

My original question about division generally was answered, plus I also learned that B4J's in-line Java is more like end-of-line Java, which explains another mystery I'd had a few weeks back. ๐Ÿคฃ
 
Last edited:
Upvote 0

QSerg

Member
Quite recently I figured out that even VB6 does not do integer division!!! It does EVERYTHING in double and then converts it to integer with rounding. So if you try 4/3 it would be 1 (correct integer division), but 5/3 will be 2 (incorrect integer division). So now if I need integer division I convert my integers into doubles, do division, apply Int function to rid off fraction and reassign result to new int. Yeh, I greatly.... not like that.... I GREATLY missing old good Turbo C where everything was simple, understandable and deterministic.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Yeh, I greatly.... not like that.... I GREATLY missing old good Turbo C where everything was simple, understandable and deterministic.
That's why I GREATLY love ๐Ÿ˜ that B4X supports in-line Jave which gives me full control over the outcome!

Global JavaObject:
Sub Class_Globals
    Private jo As JavaObject = Me     ' Needs JavaObject library
End Sub

In-line Java:
#IF JAVA
    public static int IntDiv (int a, int b){
    int result = a / b; // result will be 7 / 3 = 2 and 4 / 3 = 1
    return result;
    }
#End If

Call in-line Java:
    Log($"4 / 3 = ${jo.RunMethod("IntDiv", Array(4, 3))}"$)
    Log($"7 / 3 = ${jo.RunMethod("IntDiv", Array(7, 3))}"$)

And the magic result :
4 / 3 = 1
7 / 3 = 2
๐Ÿ™ All done ๐Ÿ˜…๐Ÿ˜‚๐Ÿคฃ

But seriously, you do have complete control over the processing of the division. If you extend the routine you can determine the accuracy of the division yourself based on the given string format and even theoretically with a Java BIGINTEGER there is no limit to the maximum value.
 
Upvote 0

QSerg

Member
That's why I GREATLY love ๐Ÿ˜ that B4X supports in-line Jave which gives me full control over the outcome!

Global JavaObject:
Sub Class_Globals
    Private jo As JavaObject = Me     ' Needs JavaObject library
End Sub

In-line Java:
#IF JAVA
    public static int IntDiv (int a, int b){
    int result = a / b; // result will be 7 / 3 = 2 and 4 / 3 = 1
    return result;
    }
#End If

Call in-line Java:
    Log($"4 / 3 = ${jo.RunMethod("IntDiv", Array(4, 3))}"$)
    Log($"7 / 3 = ${jo.RunMethod("IntDiv", Array(7, 3))}"$)

And the magic result :

๐Ÿ™ All done ๐Ÿ˜…๐Ÿ˜‚๐Ÿคฃ

But seriously, you do have complete control over the processing of the division. If you extend the routine you can determine the accuracy of the division yourself based on the given string format and even theoretically with a Java BIGINTEGER there is no limit to the maximum value.
Would be more interesting 5/3 - 7/3 and 4/3 is the same everywhere. And undeniably in C everything is MUCH simpler and you GUARANTEE that your data will be placed in corresponding registers (and you even can reinforce it) and division happens as processor doing this not like written by someone in interpreter. I do have full control even in VB as long as I know what it does. Problem that it is hidden and require much reading and experiments while in C it is nature of compiler. I never been sold on Java - way too much depends what going on around and one have to study libraries while in C one have to study processor. Later is undeniably more fundamental.
 
Upvote 0
Top