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:

QSerg

Member
Try 4\3 and 5\3 with VB, you might like it. 🍻
F$$K me!!! I programming in VB6 from earlier 2000 till now and you managed to teach old dog new tricks! Though as per my posts above I hate many part of VB greatly. For example in description of "\" operator it says "Before division is performed, the numeric expressions are rounded toByte,Integer, orLong expressions." So it is Byte, Integer or Long??? Again in C I can do (int)5/(int)3 and I am GUARANTEED result because I DO know that operands will be loaded into double-bytes registers and then integer division will be performed. Moreover it is explicitly stated that all operands if they are different will be converted to "higher" one and rules of conversion are clearly stipulated. While in VB it is still not clear what will happens with "\" operator. And then there is "variant"...... IMHO all programmers who do not declared variables explicitly must be killed with fire. As well as all languages and environments that allow to use variables without explicit declaration (leave alone Fortran where iii always will be integer :)))). But frankly in modern age of Java VM and VB pseudo-compilers when declaring variable as "int" it just about intended use and not about guarantee that it will be used exclusively in double-byte register.
 
Upvote 0

QSerg

Member
F$$K me!!! I programming in VB6 from earlier 2000 till now and you managed to teach old dog new tricks! Though as per my posts above I hate many part of VB greatly. For example in description of "\" operator it says "Before division is performed, the numeric expressions are rounded toByte,Integer, orLong expressions." So it is Byte, Integer or Long??? Again in C I can do (int)5/(int)3 and I am GUARANTEED result because I DO know that operands will be loaded into double-bytes registers and then integer division will be performed. Moreover it is explicitly stated that all operands if they are different will be converted to "higher" one and rules of conversion are clearly stipulated. While in VB it is still not clear what will happens with "\" operator. And then there is "variant"...... IMHO all programmers who do not declared variables explicitly must be killed with fire. As well as all languages and environments that allow to use variables without explicit declaration (leave alone Fortran where iii always will be integer :)))). But frankly in modern age of Java VM and VB pseudo-compilers when declaring variable as "int" it just about intended use and not about guarantee that it will be used exclusively in double-byte register.
Follow up.
After this discussion I start to read documentation :). This is what it says (in VB6) for "/" operator:
If "Both expressions are Byte, Integer, or Single variants," then result is "a Single variant unless it overflows its legal range; in which case, result is aVariant containing a Double." Thus result is Variant..... WTF????? I ALWAYS use "Option Explicit" and NEVER use F$$$$G variant because I hate it. Nevertheless VB is using variants even I never asked for that.
Yeh, I greatly.... not like that.... I GREATLY missing old good Turbo C where everything was simple, understandable and deterministic. :)))))))))
 
Upvote 0

QSerg

Member
...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 is not just slower it like 100 times slower and it is no joke or exaggeration. And it make pretty much the same impact on performance like 40 years ago. Difference is - modern equipment including mobiles is many thousand times faster, so it is working. I hate modern approach (may be I am just too old???) when for some questionable "universalism" they putting on scale performance.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Is there any way to get the castings out of the division line, without using inline Java?
Yes, compile the Java source to a library and include this library into your program.

However, this requires additional knowledge of how to compile the required jar file. Ultimately, with all IDE environments it comes down to:
  • Accept the benefits and any "idiosyncrasies" of a modern development environment, test its operation carefully to see whether it matches your expectations.
  • An "elephant path" chooses to include "idiosyncrasy" (such as a piece of Java in your B4X program).
  • Continue with your what you believe in your old programming environment with possible security risks until it no longer works with today's Windows environments.
In the past, the transition to object-based VB also led to a lot of discussion, but not to the abolition of object-based VB. It's annoying to say, but it is what is: getting older means saying goodbye to the familiar things. Finally, have fun developing programs.
 
Upvote 0

QSerg

Member
To be frankly I think for modern CPU the float/double division should be faster than int division.
It is VERY strange statement to say it politely. If float/double division happens faster then why one need to have integer division altogether? If do it properly (as in C) then division will be executed with appropriate registers. For example tiny int (aka chr) will use single register, int double and long int quadruple. That will save time on moving data and on division itself. However if stupid VB6 (as well as almost everything today) doing int division through a$$ by converting it to float then perform float division with result in variant and then convert it back to int (may round in between) then indeed straight float division will be faster. But it says nothing about "modern CPU", but indeed saying a lot about modern developing environments and saying nothing positive about them.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
But it says nothing about "modern CPU", but indeed saying a lot about modern developing environments and saying nothing positive about them.
To to say it also politely, in practice I often saw confusion between purpose and means because the first question to start was not asked:

What is the irrefutable purpose and what are the necessary means to achieve this irrefutable goal?

Resources (people, hardware, software and development environments, money and time) are means and not a purpose (with a very exceptional exception).

You will then arrive at irrefutable answers such as:
  1. A legal requirement
  2. Must replace old method with the same end result
  3. Must have the shortest possible processing time
  4. Other stated reasons
The second answer is compelling without freedom of choice, while the third answer provides freedom of interpretation. The difference between the choice not made between answers 2 and 3 leads to ambiguity in many projects and discussions about matters that are actually not relevant if answer 2 had clearly been chosen.
In practice it is interesting to ask project employees what they think is the irrefutable goal.
The answers given often make it clear how the project is progressing.😅😂🤣
 
Upvote 0

QSerg

Member
To to say it also politely.....
Too much typing using many fancy wording to convey simple thing - it does not matter how it implemented as long as it works and end result achieved faster. As least this is how I interpreted it.
However IMHO it does matter and whole topic about it - sometimes integer division is not really integer and indeed it took me whole day to discover it and find pesky data-driven bug - i.e. I did not arrived earlier. From other hand yes, modern hardware is VERY fast and nowadays we do not need count processor cycles anymore. But ask yourself - do you do your work faster in say Excel today comparing to say later 90-s (if you of course old enough)? Answer is not, may be even slower despite the fact that modern hardware literally thousands times faster. Why? Many reason and one of them is integer division in float registers.
YMMV.
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Just for reference for anyone interested in since I have not tested it by myself with the code in this article.

https://www.codeproject.com/Tips/1247235/Floating-Point-and-Integer-Arithmetic-Benchmark
屏幕截图 2024-01-16 105640.png
 
Upvote 0

QSerg

Member
Just for reference for anyone interested in since I have not tested it by myself with the code in this article.

https://www.codeproject.com/Tips/1247235/Floating-Point-and-Integer-Arithmetic-Benchmark
View attachment 149752
I would question results straight away - how came DivBigInt FASTER than DivSmallInt???? Seriously??? Just load two small int into big int register and you have some 30% increase in performance! DITTO to DivBigDouble to DivSmallDouble. Also while MulBigDouble slower than MulBigInt for some freaking reason MulSmallDouble is faster than MulSmallInt. All this lead me to believe that they using the same registers and loosing time converting things back and fort.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
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
What version of B4J are you using? I'm using 10.0 and it looks like only the denominator is cast to a double

//BA.debugLineNum = 14;BA.debugLine="Dim b As Int = 1 / 3";
_b = (int) (1/(double)3);
//BA.debugLineNum = 15;BA.debugLine="b = 1 / a.As(Int)";
_b = (int) (1/(double)(_a));
//BA.debugLineNum = 16;BA.debugLine="Dim c As Int = a / (1 * b).As(Int)";
_c = (int) (_a/(double)((int) ((1*_b))));
//BA.debugLineNum = 17;BA.debugLine="Dim d As Int = a * (1 / b)";
_d = (int) (_a*(1/(double)_b));

This seems to provide a consistent division that works for resulting byte/int/long and float/double results. I guess what is missing is an alternative that would divide without casting when the result and both operands are of the same type. Time to make a wish @emexes?

Don't know if anyone else gave that answer.

If you look at the resulting Java code, the result is already cast to an (int). The issue is that @emexes was expecting a true integer division, but B4X does not seem to provide such a feature (yet?).

Note:
According to the link below, casting the denominator to a double in Java is enough for the JVM to treat the whole operation as a double division.

Link:
 
Upvote 0

QSerg

Member
Hi.
Don't know if anyone else gave that answer.
B4X:
Log((7/3).As(Int))
Andreas.
This is not the point - I am sure all here know how to screw up any system. Point is if I do this:

int i, j,k
i=5
j=3
k=i/j

I DO EXPECT k being 1, not 2. And it should work in ANY system pretty much as I expect red signal in traffic light means STOP in ANY country.
YMMV of course.
 
Upvote 0

amykonio

Active Member
Licensed User
Longtime User
If you look at the resulting Java code, the result is already cast to an (int). The issue is that @emexes was expecting a true integer division, but B4X does not seem to provide such a feature (yet?).
Hi.
I agree. It is casted as integer. But this happens because I ask that.
B4X:
Log((7/3).As(Int))
'Produced Java: anywheresoftware.b4a.keywords.Common.LogImpl("065539",BA.NumberToString(((int) ((7/(double)3)))),0);
Log((7/3))
'Produced Java: anywheresoftware.b4a.keywords.Common.LogImpl("065540",BA.NumberToString((7/(double)3)),0);
The real "issue" is that B4J (and possible B4A) will always translate:
B4X:
7/3
'Generated java: (7/(double)3)
So if someone wants to avoid that the easiest way is to use some inline java, as other already mentioned.
Andreas.
 
Upvote 0

emexes

Expert
Licensed User
like only the denominator is cast to a double

Yeah, I wasn't thinking straight at the time, and was using decompiled bytecode rather than looking directly at the Java output of B4J.

Actually, I was thinking half-straight: I'd been intending to use disassembled bytecode, so that I could see exactly which JVM division instruction was used.
 
Upvote 0

emexes

Expert
Licensed User
the easiest way is to use some inline java

except for the anomaly that B4X inline Java isn't in-line with the compiled output, it's added at the end of the compiled output.

Thus the "inline" code has to be in a function, which adds function-call overhead, which (for short operations like this) moots the point of inlining.
 
Last edited:
Upvote 0
Top