Float Precision

I’m using doubles for some mathematical calculations and I’m getting these two values:

a = -69.49068165087722
n = 304.2372372266157

The problem is when I do this:

float fa = (float) a;
float fb = (float) b;

I get:
fa: -69.490685
fb: 304.23724

Losing a lot of the precision. Of course, this was expected but floats can’t reach at least 8 decimals? I can use six (like the fa variable in this example) but I also don’t know why the second value have even less decimal positions. How can I achieve floats of six decimals in both cases?

Thanks for any help, this is nuts.

a = -69.49068165087722d;

would be double

Thanks for your message. The thing is that I need to use floats (to send the values over OSC). How can I convert these doubles to floats but keeping at least 6 decimal positions?

float af =2;
float bf =3;
float resultf,resultffromd;
double ad=2d;
double bd=3d;
double resultd;

resultf = af/bf;
resultd = ad/bd;
resultffromd = (float)(resultd);


println("float    min: "+Float.MIN_VALUE+  "\t\t max: "+Float.MAX_VALUE);
println("double   min: "+Double.MIN_VALUE+ "\t\t max: "+Double.MAX_VALUE);

println("resultf "+resultf);
println("resultd "+resultd);
println("resultffromd "+resultffromd);

shows

float    min: 1.4E-45		 max: 3.4028235E38
double   min: 4.9E-324		 max: 1.7976931348623157E308
resultf 0.6666667
resultd 0.6666666666666666
resultffromd 0.6666667

so for float i see 7 decimales?


please show usable code here to verify your problem

If you run this code with one of the double values from my calculations:

double resultd;
float resultffromd;

resultd = -75.36681540070782;
resultffromd = (float)(resultd);

println("resultd "+resultd);
println("resultffromd "+resultffromd);

You get:
resultd -75.36681365966797
resultffromd -75.36681

resultfromd have just five decimal positions. I would need six and I don’t know why in the conversion from double to float I’m losing one. Maybe it has to do that is a negative number?

your code not run here??

resultd cannot be resolved to a variable

Actually, sometimes I get six decimal values. When the integer part of the number have three positions then my decimal count goes down again (i.e.: 322.91475198111 goes 322.915 --losing three decimal positions from six possibles)

I fixed the snippet. try again.

thanks, i see that now,
and it makes no difference if i use
75.36681540070782d;
so change the sign or the ‘d’ not help.
and float(double); even gives error


but

println( (float)(2d/3d) );

works!


what i see is:

double  resultd = -75.36681540070782; // gives -75.36681
double  resultd =  -5.36681540070782; // gives -5.3668156

and see for a 4 byte float
https://en.wikipedia.org/wiki/Single-precision_floating-point_format ,

You might find some ideas in this previous discussion helpful:

If you need precision, you could still send your data over OSC – as double directly if it is supported, or with type conversion – depending on your speed / bandwidth needs, even sending your double as a string, for example.

I don’t think that Java floating point has fixed decimal precision – the precision depends on the values. Not sure that explains your issue entirely, but it sounds like floats are not the way to go in your case. Instead, maybe work around the OSC bottleneck…

1 Like
3 Likes
double d = -75.36681540070782d;
float  f = (float)(d);
int    i = (int)(d);

float sendf = (float)( d - (double)(i) ); 
println(" d "+d+" f "+f+" i "+i);

println(" a hack could be to send 2 numbers: one integer "+i+" and a better float for the decimals only "+sendf); 

double gotd = (double)(i) + (double)(sendf);
println(" on the other side combine it again: "+gotd);

see

 d -75.36681540070782 f -75.36681 i -75
 a hack could be to send 2 numbers: 
one integer -75 and 
a better float for the decimals only -0.3668154
 on the other side combine it again: -75.36681538820267

1 Like

Here’s an untested thought for you. Maybe try using the nf() function on your double, which creates a string, then convert it back to a number. I haven’t tested it but it may work using less code.

Ok. I tested it. It worked. Try this example:
double d1,d2;

void setup() {
size(screen.width, screen.height);
d1 = 37.123456789090909
d2 = -371.123456789090909
println(d1 + " " + d2);
String dd1 = nf(d1,4,6);
String dd2 = nf(d2,4,6);
println(float(dd1)+" "+float(dd2));
}

void draw() {
background(0,0,255);
}

1 Like

very good, send a string is a valid idea
if there are no concerns about time / bandwidth

These things are all great workarounds in general cases. But if the goal is “I have doubles, and want to send them over OSC, so they have to become floats”… then no, they don’t have to become floats.

Just send OSC doubles. Problem solved.

import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;

void setup() {
  size(400,400);
  frameRate(25);
  oscP5 = new OscP5(this,12000);
  myRemoteLocation = new NetAddress("127.0.0.1",12000);
}

void draw(){
  background(0);
}

void mousePressed() {
  OscMessage myMessage = new OscMessage("/test");
  double d = 3.1415926535897932384626433832795028841971693993751;
  // 50 digits -- more than will fit in a double
  d += (int)random(100,900);
  // it will store about n.1415927410126 or so
  // w decimal matching up to n.141592
  double a = -69.49068165087722;
  double n = 304.2372372266157;
  myMessage.add(d);
  myMessage.add(a);  
  myMessage.add(n);
  oscP5.send(myMessage, myRemoteLocation); 
}

void oscEvent(OscMessage theOscMessage) {
  // double math on the receiving end
  print(millis(), "received", theOscMessage.typetag(), ": ");
  double d = theOscMessage.get(0).doubleValue();
  double a = theOscMessage.get(1).doubleValue();
  double n = theOscMessage.get(2).doubleValue();
  println(d, a, n);
  // prints ~12 decimals of precision, xxx.141592741012xx
}

6818 received ddd : 147.14159274101257 -69.49068450927734 304.23724365234375
7930 received ddd : 494.1415927410126 -69.49068450927734 304.23724365234375
8851 received ddd : 345.1415927410126 -69.49068450927734 304.23724365234375

3 Likes