B4J Question B4J vs Java Calculation

Johan Schoeman

Expert
Licensed User
Longtime User
I have this string in a text file:

B4X:
448.12024391174316,262.125

A Java project that I am trying to convert to B4J as well as my B4J project both logs this correctly (let call it an X and Y value separated by a ","

In both the B4J and Java projects the following applies:
B4X:
    width = 1280   'declared as an int
    height = 720   'declared as an int
    minusheight = height / 1.65    'declared as Double
    minuswidth = width / 2.5    'declared as Double
    devide = height / 300    'declared as Double

The confusing part is this:

B4J code:
        Dim c As ComplexNumber
        c.Initialize((s.substring2(0, comaindex) - minuswidth) / devide, _
        (s.substring2(comaindex + 1, s.length()) - minusheight) / devide)
        X.add(c)

        Log("c.re = " & c.re)
        Log("c.im = " & c.im)

Java code:
            ComplexNumber c = new ComplexNumber((Double.valueOf(s.substring(0, comaindex)) - minuswidth) / devide,
                    (Double.valueOf(s.substring(comaindex + 1, s.length())) - minusheight) / devide);
            X.add(c);
            BA.Log("c.re = " + (Double.valueOf(s.substring(0, comaindex)) - minuswidth) / devide);
            BA.Log("c.im = " + (Double.valueOf(s.substring(comaindex + 1, s.length())) - minusheight) / devide);

With the same initial value (x = 448.12024391174316 and y = 262.125) the calculation results are as follows:
B4J re value = -26.616565036773686
B4J im value = -72.59943181818183

Java re value = -31.93987804412842
Java im value = -87.11931818181819

With my calculator I calculate the results of re and im to be the same as that of the B4J code.

What is happening here? Why the difference?
 
Solution
the B4J code and inline java code yields different answers for Re and Im. The inline java code yields the correct answers. The B4J code does not.

You can make the B4J results match the Java results by forcing emulating integer division using Floor() :
B4X:
width = 1280
height = 720
minusheight = height / 1.65
minuswidth = width / 2.5
devide = Floor(height / 300)
  
time = 0.0f
Log output:
Waiting for debugger to connect...
Program started.
s = 448.12024391174316,262.125
B4J Re = -31.93987804412842
B4J Im = -87.11931818181819
Java Re = -31.93987804412842
Java Im = -87.11931818181819

Johan Schoeman

Expert
Licensed User
Longtime User
When I change the 300 to 300.0, then the inline java code is logging the same as the B4J code. Was this not our goal?

What are the Java project values? I can't find any .java files in the .zips you attached above.
I have added inline Java code in the B4J project that calcs Re and Im to compare with what the B4J code logs. They are different. We need to get the calc result to be:

Java re value = -31.93987804412842
Java im value = -87.11931818181819

Not:

B4J re value = -26.616565036773686
B4J im value = -72.59943181818183
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
When I change the 300 to 300.0, then the inline java code is logging the same as the B4J code. Was this not our goal?



What are the Java project values? I can't find any .java files in the .zips you attached above.
You dont need the java files. I have added inline java code that produces the same result as the java project that I have extracted the java code from. In the SAME b4j project the B4J code and inline java code yields different answers for Re and Im. The inline java code yields the correct answers. The B4J code does not.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Hang on: are you saying that your calculator is wrong too?
Yes. According to the original java project and the inline java code that I have added the result is not the same as the calc done by the pure b4j code. And the original java project is working.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Yes. According to the original java project and the inline java code that I have added the result is not the same as the calc done by the pure b4j code. And the original java project is working.
...or that of my HP41 calculator (app on my phone).
 
Upvote 0

emexes

Expert
Licensed User
the B4J code and inline java code yields different answers for Re and Im. The inline java code yields the correct answers. The B4J code does not.

You can make the B4J results match the Java results by forcing emulating integer division using Floor() :
B4X:
width = 1280
height = 720
minusheight = height / 1.65
minuswidth = width / 2.5
devide = Floor(height / 300)
  
time = 0.0f
Log output:
Waiting for debugger to connect...
Program started.
s = 448.12024391174316,262.125
B4J Re = -31.93987804412842
B4J Im = -87.11931818181819
Java Re = -31.93987804412842
Java Im = -87.11931818181819
 
Upvote 2
Solution

Johan Schoeman

Expert
Licensed User
Longtime User
You can make the B4J results match the Java results by emulating integer division using Floor() :

B4X:
width = 1280
height = 720
minusheight = height / 1.65
minuswidth = width / 2.5
devide = Floor(height / 300)
   
time = 0.0f
Log output:
Waiting for debugger to connect...
Program started.
s = 448.12024391174316,262.125
B4J Re = -31.93987804412842
B4J Im = -87.11931818181819
Java Re = -31.93987804412842
Java Im = -87.11931818181819
Omg! Would never have got to this. What is the rationale behind using Floor?
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Good discussion for a reminder to notice this double/int problem. I am thinking maybe part of my code also has this risk. I gather for calculation better to use double for all then cast to int if needed.
 
Upvote 0

emexes

Expert
Licensed User
Omg! Would never have got to this. What is the rationale behind using Floor?

Because the Java code is performing an integer division:

Java:
height = 720   'declared as an int
devide = height / 300    'declared as Double

whereas the BASIC "/" is usually a floating point division. Floor() removes the fractional component, converting a floating point value to an integer.

Well, for positive numbers, at least, but division here is always of two positive values, so the result will always be positive too.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Because the Java code is performing an integer division:

Java:
height = 720   'declared as an int
devide = height / 300    'declared as Double

whereas the BASIC "/" is usually a floating point division. Floor() removes the fractional component, converting a floating point value to an integer.

Well, for positive numbers, at least, but division here is always of two positive values, so the result will always be positive too.
So why not Floor these as well:
minusheight = height / 1.65
minuswidth = width / 2.5

It does not yield the correct results when Flooring them too but trying to understand why Flooring "divide" works but not when Flooring "minusheight" and "minuswidth" too.

But your solution is working - it gives the correct answer! Very sharp @emexes ! Now I get the correct sorted amplitudes after the remainder of the code has executed.
 
Upvote 0

emexes

Expert
Licensed User
Omg! Would never have got to this. What is the rationale behind using Floor?

Or do you mean as in: why use Floor() instead of .As(Int) ?

The reason was that I know what Floor() does (it rounds down) whereas I wasn't sure if "casting" in B4X rounded to nearest or rounded down.

Could be worse: ever heard of bankers' rounding? Or round-to-even? Lol, so many traps.
 
Upvote 0

emexes

Expert
Licensed User
So why not Floor these as well:
minusheight = height / 1.65
minuswidth = width / 2.5

They are dividing by real ("floating point") numbers, so *presumably* should be using real (floating point) division.

But I agree it is odd that the some of the divisions are integer and some are real ("floating point").

If it was intentional, then it would have been nice if the original programmer had documented the reasons for it, and applied some castings to make it more obvious.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
They are dividing by real ("floating point") numbers, so *presumably* should be using real (floating point) division.

But I agree it is odd that the some of the divisions are integer and some are real ("floating point").

If it was intentional, then it would have been nice if the original programmer had documented the reasons for it, and applied some castings to make it more obvious.
It is amazing what Floor does - it corrected a 16% error in both Re and Im.

Just imagine you are launching from earth to the moon and one of your calcs should have "Floored" a value but you did not. So a bad scenario is that your trajectory is out by 16%. Will have to burn a lot of fuel to correct the error.
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Will have to burn a lot of fuel to correct the error.

or worse... there was a rocket that broke up (closely followed by blowing up) thanks to a poor type conversion (I think was more an overflow issue, but it's in the ballpark of what you're describing). Hundreds of millions of dollars of satellites lost as well.

Hang on, let me look it up, rather than me spout wrong info. Plus there was another ripper rocket explosion anomaly video, I think a Delta with GPS satellites.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
They are dividing by real ("floating point") numbers, so *presumably* should be using real (floating point) division.

But I agree it is odd that the some of the divisions are integer and some are real ("floating point").

If it was intentional, then it would have been nice if the original programmer had documented the reasons for it, and applied some castings to make it more obvious.
There was method in the madness....does not seem as if the "flooring" has too much of an effect on the final result. But thanks for your patience and solution to get this to work.

 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Well, I know that thread already have a solution... and I understand why "programmers" using sometimes int, double or anything that limit numbers..

At last years prefer using "double" for numbers even if i need int or long (old happy basic user).. because those digits after dot "0.00" - cost for TAX... and cost more if have some more calculations like Johan...

So for business apps always use double even if i don't need it... and at the end of "calculations" set it to the right variable (int, double, whatever need, etc) - if want also round... but always at the end...

Ofcourse if many calcs and variables... may be hit memory limits... (like old limits of 64K)
At least... me already hit :eek: ??
 
Upvote 0

BlueVision

Active Member
Licensed User
Longtime User
Just imagine you are launching from earth to the moon and one of your calcs should have "Floored" a value but you did not. So a bad scenario is that your trajectory is out by 16%. Will have to burn a lot of fuel to correct the error.
That made me smile. Unfortunately, I only discovered this thread very late, I currently have a small problem with one red bar too many on the test strip...
I can reassure you Johan, this error would have been noticed earlier. At the latest with the orbit calculations for the orbit of the moon itself. As you may remember, I had exactly the same problem when implementing the orbit calculations for the Earth's satellite in my compass app, where I really wanted to map the moon and the sun to the corresponding position on the compass rose. I encountered the same problem there. Extreme deviations in the calculations due to minimal rounding differences in the floating point arithmetic. Well, at some point I solved the problem after weeks by reading a lot about orbital position calculations and then somehow got a usable result. I can't even say whether everything is 100% correct. But somehow it works for my purposes.
And one way or another, you always stumble across things like this. Have any of you ever tried to accurately calculate the movable Christian holidays and transfer them to our modern calendar system? It just gives you a headache at some point.
I had all the more respect for a mathematician who solved this problem for us centuries ago: C.F. Gauss. I still haven't completely understood his "Easter formula", but it works.

Back to the moon for a moment: please take a look at the film "HIDDEN FIGURES". A great film for several reasons. I still don't understand how the Americans managed (and dared) to fly to the moon and back again with an on-board computer that was not much more than a "pocket calculator" of our days. My respect for that. At the same time, it is all the more shocking to see how this was compatible with the racial ideology of the time, which is also beautifully and lovingly portrayed in this film. Take a look at this film. And well, I'm also a little proud of the first NASA "supercomputer" shown in the film, an IBM 7090, because I worked many years for IBM. A great time.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
And one way or another, you always stumble across things like this. Have any of you ever tried to accurately calculate the movable Christian holidays and transfer them to our modern calendar system? It just gives you a headache at some point.
I had all the more respect for a mathematician who solved this problem for us centuries ago: C.F. Gauss. I still haven't completely understood his "Easter formula", but it works.
CelebrationBook-Εορτολόγιο
(it is a greek Christian orthodox holidays - but you will get the headache you want) :)
 
Upvote 0
Top