Issues when applying a formula

Hi there, I am trying to apply the next formulas on my Processing code for my project:

In order to do that, I wrote the next code:

float a = 6378388.0;
float b = 6356911.94613;

float e = sqrt(sq(a) - sq(b))/a; 
println("e =", e);
float e2 = sqrt(sq(a) - sq(b))/b; 
println("e' =", e2);

This code prints some values that, even thought they are similar to the expected ones, differ a bit on the last numbers. This could seem unsignificant, but I’m working with coordinates and I need the highest precission possible. Here there is a table with the values given by the example I’m following, the values that Python printed (because I made a test with Python to see if other programming languages could do it well) and the values Processing did:

Source e e’
Example 0.08199189 0.08226889
Python 0.08199188997511561 0.08226888960338334
Processing 0.08199162 0.08226862

As you can see, they are similar, but Processing’s last numbers make no sense. I don’t know why do this happen, and I couldn’t find any information about it.

This is the Python code I used, if you think it can be useful to solve the problem with Processing:

import math

a = 6378388.0
b = 6356911.94613

e = math.sqrt(a**2-b**2)/a
e2 = math.sqrt(a**2-b**2)/b
print(e, e2)

I hope someone can help me, thanks.

Processing uses the 32-bit float primitive datatype as its default floating-point precision:

For 64-bit floating-point precision we use double instead:

However, it’s not enough to simply declare variables w/ primitive datatype double!

We also must suffix any floating-point literal w/ a d, so it uses a 64-bit storage: 6356911.94613d

Without it, 6356911.94613 would be coerced to 6356912.0 due to 32-bit storage constraint!

Plus all Processing’s math functions need to be replaced w/ their corresponding Java’s Math class version:

final double a = 6378388;
final double b = 6356911.94613d;

final double ab = Math.sqrt(a*a - b*b);

final double e1 = ab / a; 
println("e1 =", e1);

final double e2 = ab / b; 
println("e2 =", e2);

4 Likes

I see @GoToLoop has clearly explained the difference between the float and double data types but I will add my code solution because

  1. I created it before I read GoToLoops reply and
  2. I have created a function to do the maths for any a,b

:grinning:

double a = 6378388.0D;
double b = 6356911.94613D;

void setup() {
  println(e(a, b, a));
  println(e(a, b, b));
}

double e(double a, double b, double div) {
  return Math.sqrt(a * a - b * b)/div;
}
3 Likes

You’ve forgotten to suffix that high-precision floating-point literal w/ a d: :wink:
double b = 6_356_911.94613D;

2 Likes

Well spotted and I have corrected the code in my post. Although not needed for a I have added it anyway to indicate to the coder that a literal double value is expected here. Useful if the value has to be edited later.

2 Likes

I had a similar issue with datatype Long.

The issue was the internal (invisible) conversion of the number to String performed by the text() command (or the println() command). So even when the program got it right, the output was wrong.

To avoid this, glv suggested Long.toString(number) which was great.

Maybe there’s also Double.toString(number)

2 Likes

The only overloading datatype version missing for both println() & print() is short; which would be auto-coerced to int anyways:

Therefore both printing functions should have no problem at all console-logging whatever datatype argument we pass to them; with the notably only exception for short[] arrays!

BtW, datatype short[] is the only datatype Processing functions can’t properly deal with at all!

On the other hand, method text() is indeed more restrictive for the available overloading datatype signatures for its parameters.

Besides the obviously String datatype, it has overloaded signatures for int, float, char and even char[] datatypes.

Arguments of primitive datatypes byte & short would be nicely auto-coerced to int.

However, we wouldn’t be able to pass arguments of primitive datatypes boolean, long and double; neither for any non-primitive datatypes apart from String!

All of those non-supported datatypes would need to be converted to String before invoking text(), as you have already found out.

But a much simpler "" + arg would coerce any of those argument datatypes to String just fine, as long as they’re not arrays.

4 Likes

Math should probably be done in pure Java.

Processing seems to be slow at math for no good reason.

According to VisualVM, my own distance method, fastDist, uses WAY less CPU than using Processing’s dist() method.

private static double fastDist(double x1, double y1, double x2, double y2) {
  return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

“…for no good reason.”

Processing consciously trades raw power for approachability and beginner-friendliness.

dist() is a neat and compact way to handle that oft-used calculation. The compromise is that it has overhead.

You can use sqrt() and pow() to write out that formula. I’m sure they perform OK against their respective Math counterparts.

1 Like

In the Java class libraries all internal math calculations are done using the double data type but when Processing was first created they decided to use float as the default data type for the Processing language.

So when the Processing executes the statement
float v = sqrt(3.14159);

it calls the equivalent Java method parameter value is passed to the Java method
Math.sqrt(3.14059);

but this method returns a double which has to be cast to a float. Using the Processing sqrt method involves

  1. an extra function call
  2. a cast of the Java result back to a float

Personally I think using float instead of double was a mistake, it has 2 adverse consequences

  1. Decreases performance. With modern processors and JVM optimisation this should not be a major problem, certainly it has never impacted me but might be an issue for others.
  2. Some problems require the use of the double data type because they cannot be solved using float variables. For me this is the more critical issue and all my Processing libraries use the double data type internally because of this.
4 Likes

Always so many detailed insights, love it!

Though I’m intrigued by your “float was a mistake” statement.

In my mind, close to all discussions on limitations and underperformance in Processing can be answered with “it’s a deliberate compromise in service of our core target audience”.

My theory on why float made it over double; Put yourself in the mind of that coding newbie, starting out with drawing a few basic shapes onto the screen. As if grokking the concept of a variable wasn’t enough, they’re also dealing with a typed programming language. The first variable types they’ll encounter are most likely int and float. The good thing is, there are number analogues they know already – “whole numbers” and “numbers with a decimal point”. Being able to fall back on these real world analogues in an otherwise alien programming environment is super valuable.
Imagine now that the next type after int is a double. “It’s a number with a decimal point, but in fact you need to think of two different types of decimal point numbers, float and double, and you want to use one for tasks X and the other for tasks Y and in Processing we are using the more advanced version”. That’s immediately a bigger hurdle to deal with. And if you can consciously hide away that complexity by way of simplification, then I’m all for it, even if it means to let go of the advantages double can offer.

But maybe those arguments are irrelevant to one of the major user groups in Processing? Truth be told, I’ve never written a sketch that required double and I’m pretty sure I went 10+ years fuzzing around in Processing before even becoming aware that there’s an “older sibling to float”.

All this being said, I’m fully willing to accept that I’m way off with my “core target audience” argument. Possibly I’m sorely underestimating what you can expect a newbie to understand. But I’ve seen so many newcomer questions trip over such banal topics, that I feel the decision to err on the side of simplicity over power is the correct one.

1 Like

The Processing helper functions can be found here in PApplet.java to see what is going on under the hood:

sqrt() :

  static public final float sqrt(float n) {
    return (float)Math.sqrt(n);
  }

dist() :

  static public final float dist(float x1, float y1, float x2, float y2) {
    return sqrt(sq(x2-x1) + sq(y2-y1));
  }

:)

1 Like

Consider metallurgists, doctors, engineers, artists, footballers, actors, builders, plumbers … every specialist discipline has its own ‘vocabulary’. This is essential because it allows specialists to communicate complex details, information and ideas accurately and rapidly; thereby making it easier to improve and enhance their specialism.

As pre-school infants we are exposed to whole numbers but once at school we learn to use fractions followed by decimals. It allowed us to count and share the sweets out equally :grinning: Later we would be introduced to new words like integer numbers and floating point numbers.

Now consider the newbie to Processing which is basically a wrapper framework built around Java which is a strongly-typed language. The newbie has to learn a new ‘vocabulary’ and my contention is we could teach either

  1. float is the data type to be used for decimal numbers, or
  2. double is the data type to be used for decimal numbers

From a teaching and learning perspective I do not see the problem with going with (2). After all the newbie is going to have a lot more complex concepts to master if they want to get on.

Did you know that Processing created the keyword color as an alias to int

int c = color(255, 128, 128);
color c = color(255, 128, 128);

Both of these statements do the same thing but in the second line color represents both a data type and a function name. Personally I think this was their second and last mistake when they created Processing.

Don’t get me wrong, I think Processing is a wonderful way to get started in programming but the newbie must be prepared to learn the vocabulary of the computer programmer.

Finally the creators of Processing must be congratulated on making the object orientated language Java look like a procedural language and thereby making it accessible to all. :+1:

2 Likes

I don’t see why my own distance method that is higher precision should be faster for the exact same task.

The default should be almost exactly the same speed.

How is this possible?
I thought stuff can’t be static and final?

static public final float sqrt(float n) {
  return (float)Math.sqrt(n);
}

Err… mag is different from dist.

Hmm… I fell for what the Germans call Gefährliches Halbwissen. I assumed that in programming languages float was always the “general use” type and double the “speciality case” type. Hence my “Why apply the more advanced type as default?” stance. Turns out this differentation ain’t necessarily so. Goes to show that I need to understand more and better, before digging my heels in.

Testing:

:)

1 Like

static is a Java keyword that is used to declare fields, methods and classes which can be accessed w/o instantiating the class they belong to; meaning they are independent from a particular instance of its class.

So the method PApplet.sqrt() can be invoked w/o requiring to instantiate its PApplet class.

The keyword final when used to declare fields, variables & parameters, it disallows them to be re-assigned w/ another value; although mutable objects they refer to can still be changed.

final methods can’t be @override by subclasses; and final classes themselves can’t be subclassed at all.

1 Like