How to alter double by its smallest increment - java

Is something broken or I fail to understand what is happening?
static String getRealBinary(double val) {
long tmp = Double.doubleToLongBits(val);
StringBuilder sb = new StringBuilder();
for (long n = 64; --n > 0; tmp >>= 1)
if ((tmp & 1) == 0)
sb.insert(0, ('0'));
else
sb.insert(0, ('1'));
sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']');
return sb.toString();
}
public static void main(String[] argv) {
for (int j = 3; --j >= 0;) {
double d = j;
for (int i = 3; --i >= 0;) {
d += Double.MIN_VALUE;
System.out.println(d +getRealBinary(d));
}
}
}
With output:
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001]
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010]
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011]

The general idea is first convert the double to its long representation (using doubleToLongBits as you have done in getRealBinary), increment that long by 1, and finally convert the new long back to the double it represents via longBitsToDouble.
EDIT: Java (since 1.5) provides Math.ulp(double), which I'm guessing you can use to compute the next higher value directly thus: x + Math.ulp(x).

Floating point numbers are not spread out uniformly over the number line like integer types are. They are more densely packed near 0 and very far apart as you approach infinity. Therefore there is no constant that you can add to a floating point number to get to the next floating point number.

Your code is not well-formed. You try to add the minimum double value and expect the result to be different from the original value. The problem is that double.MinValue is so small that the result is rounded and doesn't get affected.
Suggested reading: http://en.wikipedia.org/wiki/Machine_epsilon
On the Wikipedia article there is the Java code too. Epsilon is by definition the smallest number such as (X + eps * X != X), and eps*X is called "relative-epsilon"

Since Java 1.8 there is java.lang.Math.nextUp(double) doing exactly what you want. There is also opposite java.lang.Math.nextDown(double).

In case you want to use the BigDecimal class, there is the BigDecimal.ulp() method as well.

Related

Get a numer decimal part as Integer using only math

Edit: This has to do with how computers handle floating point operations, a fact that every programmer faces once in a lifetime. I didn't understand this correctly when I asked the question.
I know the simplest way to start dealing with this would be:
val floatNumber: Float = 123.456f
val decimalPart = floatNumber - floatNumber.toInt() //This would be 0.456 (I don't care about precision as this is not the main objective of my question)
Now in a real world with a pen and a piece of paper, if I want to "convert" the decimal part 0.456 to integer, I just need to multiply 0.456 * 1000, and I get the desired result, which is 456 (an integer number).
Many proposed solutions suggest splitting the number as string and extracting the decimal part this way, but I need the solution to be obtained mathematically, not using strings.
Given a number, with an unknown number of decimals (convert to string and counting chars after . or , is not acceptable), I need to "extract" it's decimal part as an integer using only math.
Read questions like this with no luck:
How to get the decimal part of a float?
How to extract fractional digits of double/BigDecimal
If someone knows a kotlin language solution, it would be great. I will post this question also on the math platform just in case.
How do I get whole and fractional parts from double in JSP/Java?
Update:
Is there a "mathematical" way to "calculate" how many decimals a number has? (It is obvious when you convert to string and count the chars, but I need to avoid using strings) It would be great cause calculating: decimal (0.456) * 10 * number of decimals(3) will produce the desired result.
Update 2
This is not my use-case, but I guess it will clarify the idea:
Suppose you want to calculate a constant(such as PI), and want to return an integer with at most 50 digits of the decimal part of the constant. The constant doesn't have to be necessarily infinite (can be for example 0.5, in which case "5" will be returned)
I would just multiply the fractional number by 10 (or move the decimal point to the right) until it has no fractional part left:
public static long fractionalDigitsLong(BigDecimal value) {
BigDecimal fractional = value.remainder(BigDecimal.ONE);
long digits;
do {
fractional = fractional.movePointRight(1); // or multiply(BigDecimal.TEN)
digits = fractional.longValue();
} while (fractional.compareTo(BigDecimal.valueOf(digits)) != 0);
return digits;
}
Note 1: using BigDecimal to avoid floating point precision problems
Note 2: using compareTo since equals also compares the scale ("0.0" not equals "0.00")
(sure the BigDecimal already knows the size of the fractional part, just the value returned by scale())
Complement:
If using BigDecimal the whole problem can be compressed to:
public static BigInteger fractionalDigits(BigDecimal value) {
return value.remainder(BigDecimal.ONE).stripTrailingZeros().unscaledValue();
}
stripping zeros can be suppressed if desired
I am not sure if it counts against you on this specific problem if you use some String converters with a method(). That is one way to get the proper answer. I know that you stated you couldn't use String, but would you be able to use Strings within a Custom made method? That could get you the answer that you need with precision. Here is the class that could help us convert the number:
class NumConvert{
String theNum;
public NumConvert(String theNum) {
this.theNum = theNum;
}
public int convert() {
String a = String.valueOf(theNum);
String[] b = a.split("\\.");
String b2 = b[1];
int zeros = b2.length();
String num = "1";
for(int x = 0; x < zeros; x++) {
num += "0";
}
float c = Float.parseFloat(theNum);
int multiply = Integer.parseInt(num);
float answer = c - (int)c;
int integerForm = (int)(answer * multiply);
return integerForm;
}
}
Then within your main class:
public class ChapterOneBasics {
public static void main(String[] args) throws java.io.IOException{
NumConvert n = new NumConvert("123.456");
NumConvert q = new NumConvert("123.45600128");
System.out.println(q.convert());
System.out.println(n.convert());
}
}
output:
45600128
456
Float or Double are imprecise, just an approximation - without precision. Hence 12.345 is somewhere between 12.3449... and 12.3450... .
This means that 12.340 cannot be distinghuished from 12.34. The "decimal part" would be 34 divided by 100.
Also 12.01 would have a "decimal part" 1 divided by 100, and too 12.1 would have 1 divided by 10.
So a complete algorith would be (using java):
int[] decimalsAndDivider(double x) {
int decimalPart = 0;
int divider = 1;
final double EPS = 0.001;
for (;;) {
double error = x - (int)x;
if (-EPS < error && error < EPS) {
break;
}
x *= 10;
decimalPart = 10 * decimalPart + ((int)(x + EPS) % 10);
divider *= 10;
}
return new int[] { decimalPart, divider };
}
I posted the below solution yesterday after testing it for a while, and later found that it does not always work due to problems regarding precision of floats, doubles and bigdecimals. My conclusion is that this problem is unsolvable if you want infinite precision:
So I re-post the code just for reference:
fun getDecimalCounter(d: Double): Int {
var temp = d
var tempInt = Math.floor(d)
var counter = 0
while ((temp - tempInt) > 0.0 ) {
temp *= 10
tempInt = Math.floor(temp)
counter++
}
return counter
}
fun main(args: Array <String> ) {
var d = 3.14159
if (d < 0) d = -d
val decimalCounter = getDecimalCounter(d)
val decimalPart = (d - Math.floor(d))
var decimalPartInt = Math.round(decimalPart * 10.0.pow(decimalCounter))
while (decimalPartInt % 10 == 0L) {
decimalPartInt /= 10
}
println(decimalPartInt)
}
I dropped floats because of lesser precision and used doubles.
The final rounding is also necessary due to precision.

String representation of a number

So I was asked this question in a recent interview. There are two numbers, really large and thus they are represented as Strings. Now write a function to multiply them and come up with a resultant String.
This was the solution, I managed to come up with, but I think it's an impossible problem.
I'm using Integer for example.
public String multiply(String str1, String str2){
int count = 0;
for(int i=0; i < str1.length(); i++){
int num1 = Integer.parseInt(str1.substring(str1.length()-2 -i, str2.length()-1-i));
for(int j=0; j < str2.length(); j++){
int num2 = Integer.parseInt(str2.substring(str2.length()-1 -j, str2.length()-1);
count+= num1*num2;
}
}
return String.valueOf(count);
}
However, I feel that since the premise of the problem is that the numerical values of the two strings cannot be stored in a variable then the variable count will also overflow. Thus I think my solution is incorrect. Is there a way to do this. The numbers are beyond the scope of Long or any possible numeric type available.
Generally, you could use BigInteger or BigDecimal for something like this...
final String number1 = "12345678902374287346293649376492342...";
final String number2 = "12345678902374287346293649376492342...";
final BigDecimal result = new BigDecimal(number1).multiply(new BigDecimal(number2));
System.out.println("Huge Number: " + result);
The problem of "big integers" is very well handled by a number of programming languages and libraries, such as the BigInteger class. In terms of implementing it yourself, there are different ways to approach the problem, depending on what your needs are (e.g. computational efficiency vs. storage efficiency).
The basic idea is to break the arithmetic down into manageable chunks, just like arithmetic you probably learned in school. If you're storing the number in decimal as a string of digits, then you'd simply do digit-by-digit decimal multiplication, starting at the least significant digit (probably the right-hand end). If the result of any digit multiplication is 10 or more, you carry the extra ten(s) across and add it to the calculation of the next digit.
There are some example implementations here: An interview question - implement Biginteger Multiply
Using BigDecimal multiply method it rather a simple answer to this question.
See https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
Instead of using BigDecimal, you can follow the comment provided by #svasa.
You should consider the count to be a String as well.
From my experience they want you to implement the multiplication algorithm much like the one you were taught in elementary school.
the complexity is O ( N ^ 2 ) for the "manual" aproach. Better is to use an exotic algorithm such as https://en.wikipedia.org/wiki/Karatsuba_algorithm or peek an existing class from your base class library (java / C# or whatever .. such as BigInteger)
They want String, which is circumstantial, but you can decompose, till they loose interest.
String multiply(String x, String y) {
String sum = "0";
String pow10 = "";
for (int i = 0; i < x.length(); ++i) {
char digit = x.charAt(x.length() - 1 - i);
String term = multiplyDigit(digit, y);
sum = add(sum, term + pow10);
pow10 += "0";
}
return sum;
}
And so on: add, multiplyDigit.
The choice of data: char arrays, maybe digit values (byte), StringBuilder (flexible length) order and such is not really helpful for a quick implementation here (in java that is).
You could spare yourself much juggling by simplification as:
String multiplyDigit(char c, String x) {
String carries = "0";
String term = "";
int cvalue = c - '0';
for (int i = 0; i < x.length(); ++i) {
char digit = x.charAt(x.length() - 1 - i);
int product = cvalue * (digit - '0');
char carry = (char)('0' + (product / 10));
char t = (char)('0' + (product % 10));
carries = carry + carries;
term = t + term;
}
return add(carries, term);
}
where you do not add the carry immediately, but reuse add(String, String).

Why does my code return 1 always?

double formula1, formula2;
int plus;
int VALUE = 10000;
private void processFormula2()
{
for (int k = 0; k <= VALUE; k++) {
if (k % 2 != 0) {
if (plus % 2 == 0) {
double math = 1/k;
formula2 += math;
System.out.println("Getting Formula: "+ formula2);
plus++;
} else {
formula2 -= 1/k;
plus++;
}
// System.out.println("Term: " + formula2);
}
}
}
I am trying to get my formula to print out the result of Pi based off this formula that my teacher gave us. But for some reason it just returns 1.0, not really sure why. Any help or suggestions would be appreciated :)
Here's the problem:
double math = 1/k;
and
formula2 -= 1/k;
k is an int variable, so the JVM won't never return a decimal number in this statement. It will take only two possible values: 0 (if k > 1) or 1 (if k == 1) because the JVM performs the division before promoting the result to double.
Try this:
formula2 -= 1/(double)k;
Take a look at Numeric Promotions
Firstly, there are multiple errors with variable declaration.
double math = 1/k;will not truly work in Java due to how integer division is handled. You must either cast '1' to a double like double math = (double)1/k; or specify that you are using mixed mode arithmetic by using double math = 1.0/k;. This is also a problem for your formula2 variable (Along with you should always initialize your variables like formula1, formula2, and plus). You must also do the same thing with formula2 -= 1/k;.
Secondly, we have no idea what you are setting those variables to in the first place, nor do we have any test cases to compare to.

How do I parse non-integer octals in Java?

This may not be possible, but I figured it can't hurt to ask.
I have a program that needs to convert non-integer decimals into octal notation. From what I can tell, Java can only handle integer octals automatically. I've cobbled together something of a kludge, which involves breaking down the number into powers of eight, something like this.
.abcd = x * (1/8) + y * (1/64) + z * (1/512) + ......
which would be displayed as "0.xyz", if that makes any sense. The problem is, this is resulting in a lot of rounding/truncation errors for long numbers. Is there a better way to do this?
(edit)
Here's the algorithm I've been using to process the digits to the right of the decimal point:
double floatPartNum = Double.parseDouble("0." + temps[1]);
if (floatPartNum > 0) {
int p = 1;
result = result + ".";
while (floatPartNum > 0 && p < 16) {
double scale = 1/(Math.pow(8, p));
int modT = (int)( floatPartNum / scale );
result = result + modT;
double modScale = (double)modT * scale;
floatPartNum -= modScale;
p++;
}
}
I know of no floating point or fixed point support for octal numbers in base Java. If you show your algorithm for extracting the octal digits from the decimal, maybe we could help reduce the error.
There are some methods in the Float and Double classes that allow you to get the bit-wise representation of the number; for example Double.doubleToLongBits(double).
You could then extract the mantissa and exponent parts from the double-as-bits, and convert them to your octal format with no loss of precision.
However, it might be simpler to just fix your current algorithm. I'd have thought that you should be able to implement your approach without loss of precision. (Have you considered the possibility that the precision has already been lost; i.e. in the processes / calculations that produced your numbers in the first place?)
Your p < 16 is artificially truncating your output. When I try your code on 1.0/3.0, I get 0.252525252525252, but there's actually enough precision in the double to add three more octal digits, yielding 0.252525252525252525, if you change that to p < 20. But if you're concerned about "long numbers", then you might find that double just isn't big enough for your needs.
By the way, your loop can be simplified significantly, to:
for(int p = 1; floatPartNum > 0 && p < 20; ++p)
{
floatPartNum *= 8.0;
result = result + (int)floatPartNum;
floatPartNum -= (int)floatPartNum;
}
(tested), which eliminates all the need for Math.pow and so on. (Math.pow works by performing logarithms and exponentiations; it's overkill, and potentially roundoff-prone, when you're just multiplying by eight.)
How about something more like this?:
String result = "";
double floatPartNum = temps[1];
if( floatPartNum > 0 )
{
int p = 1;
result = result + ".";
while( floatPartNum > 0 && p < 16 )
{
floatPartNum *= 8.0D;
int modT = (int)floatPartNum;
floatPartNum -= modT;
result = result + modT;
p++;
}
}
Much fewer operations to introduce errors. (I am sorry I can't test this code before posting it, I am not near my programming tools.)

Implementing exponential moving average in Java

I essentially have an array of values like this:
0.25, 0.24, 0.27, 0.26, 0.29, 0.34, 0.32, 0.36, 0.32, 0.28, 0.25, 0.24, 0.25
The above array is oversimplified, I'm collecting 1 value per millisecond in my real code and I need to process the output on an algorithm I wrote to find the closest peak before a point in time. My logic fails because in my example above, 0.36 is the real peak, but my algorithm would look backwards and see the very last number 0.25 as the peak, as there's a decrease to 0.24 before it.
The goal is to take these values and apply an algorithm to them which will "smooth" them out a bit so that I have more linear values. (ie: I'd like my results to be curvy, not jaggedy)
I've been told to apply an exponential moving average filter to my values. How can I do this? It's really hard for me to read mathematical equations, I deal much better with code.
How do I process values in my array, applying an exponential moving average calculation to even them out?
float[] mydata = ...
mySmoothedData = exponentialMovingAverage(mydata, 0.5);
float[] exponentialMovingAverage(float[] input, float alpha) {
// what do I do here?
return result;
}
To compute an exponential moving average, you need to keep some state around and you need a tuning parameter. This calls for a little class (assuming you're using Java 5 or later):
class ExponentialMovingAverage {
private double alpha;
private Double oldValue;
public ExponentialMovingAverage(double alpha) {
this.alpha = alpha;
}
public double average(double value) {
if (oldValue == null) {
oldValue = value;
return value;
}
double newValue = oldValue + alpha * (value - oldValue);
oldValue = newValue;
return newValue;
}
}
Instantiate with the decay parameter you want (may take tuning; should be between 0 and 1) and then use average(…) to filter.
When reading a page on some mathmatical recurrence, all you really need to know when turning it into code is that mathematicians like to write indexes into arrays and sequences with subscripts. (They've a few other notations as well, which doesn't help.) However, the EMA is pretty simple as you only need to remember one old value; no complicated state arrays required.
I am having a hard time understanding your questions, but I will try to answer anyway.
1) If your algorithm found 0.25 instead of 0.36, then it is wrong. It is wrong because it assumes a monotonic increase or decrease (that is "always going up" or "always going down"). Unless you average ALL your data, your data points---as you present them---are nonlinear. If you really want to find the maximum value between two points in time, then slice your array from t_min to t_max and find the max of that subarray.
2) Now, the concept of "moving averages" is very simple: imagine that I have the following list: [1.4, 1.5, 1.4, 1.5, 1.5]. I can "smooth it out" by taking the average of two numbers: [1.45, 1.45, 1.45, 1.5]. Notice that the first number is the average of 1.5 and 1.4 (second and first numbers); the second (new list) is the average of 1.4 and 1.5 (third and second old list); the third (new list) the average of 1.5 and 1.4 (fourth and third), and so on. I could have made it "period three" or "four", or "n". Notice how the data is much smoother. A good way to "see moving averages at work" is to go to Google Finance, select a stock (try Tesla Motors; pretty volatile (TSLA)) and click on "technicals" at the bottom of the chart. Select "Moving Average" with a given period, and "Exponential moving average" to compare their differences.
Exponential moving average is just another elaboration of this, but weights the "older" data less than the "new" data; this is a way to "bias" the smoothing toward the back. Please read the Wikipedia entry.
So, this is more a comment than an answer, but the little comment box was just to tiny. Good luck.
Take a look at this.
If your noise has zero average, consider also the use of a Kalman filter.
In a rolling manner.... i also use commons.apache math library
public LinkedList EMA(int dperiods, double alpha)
throws IOException {
String line;
int i = 0;
DescriptiveStatistics stats = new SynchronizedDescriptiveStatistics();
stats.setWindowSize(dperiods);
File f = new File("");
BufferedReader in = new BufferedReader(new FileReader(f));
LinkedList<Double> ema1 = new LinkedList<Double>();
// Compute some statistics
while ((line = in.readLine()) != null) {
double sum = 0;
double den = 0;
System.out.println("line: " + " " + line);
stats.addValue(Double.parseDouble(line.trim()));
i++;
if (i > dperiods)
for (int j = 0; j < dperiods; j++) {
double var = Math.pow((1 - alpha), j);
den += var;
sum += stats.getElement(j) * var;
System.out.println("elements:"+stats.getElement(j));
System.out.println("sum:"+sum);
}
else
for (int j = 0; j < i; j++) {
double var = Math.pow((1 - alpha), j);
den += var;
sum += stats.getElement(j) * var;
}
ema1.add(sum / den);
System.out.println("EMA: " + sum / den);
}
return ema1;
}
public class MovingAvarage {
public static void main(String[] args) {
double[] array = {1.2, 3.4, 4.5, 4.5, 4.5};
double St = 0D;
for(int i=0; i<array.length; i++) {
St = movingAvarage(St, array[i]);
}
System.out.println(St);
}
private static double movingAvarage(double St, double Yt) {
double alpha = 0.01, oneMinusAlpha = 0.99;
if(St <= 0D) {
St = Yt;
} else {
St = alpha*Yt + oneMinusAlpha*St;
}
return St;
}
}
If you're having trouble with the math, you could go with a simple moving average instead of exponential. So the output you get would be the last x terms divided by x. Untested pseudocode:
int data[] = getFilled();
int outdata[] = initializeme()
for (int y = 0; y < data.length; y++)
int sum = 0;
for (int x = y; x < y-5; x++)
sum+=data[x];
outdata[y] = sum / 5;
Note that you will need to handle the start and end parts of the data since clearly you can't average the last 5 terms when you are on your 2nd data point. Also, there are more efficient ways of calculating this moving average(sum = sum - oldest + newest), but this is to get the concept of what's happening across.

Categories