I have created a method to create some random double values for example 10 values : num1, num2, …num10 which sum of this 10 values is 1 : num1+num2+…+num10 = 1
My method is like the method in forum
Getting N random numbers that the sum is M :
private static double[] randSum(int n, double m) {
Random rand = new Random();
double randNums[] = new double[n], sum = 0;
for (int i = 0; i < randNums.length; i++) {
randNums[i] = rand.nextDouble();
sum += randNums[i];
}
for (int i = 0; i < randNums.length; i++) {
randNums[i] /= sum * m;
}
return randNums;
}
But this method create very long numbers like: 0.18593711849349975
I even used Math.round() method but with this method my numbers are 0.0, 0.5, 0.0 , …
I need numbers from 0.01 to 0.99 or 0.1 to 0.9. If I was using integer numbers I could do this with something like Random.nextInt(0.98) +0.01 , but nextDouble() method doesn’t accept parameters, how can I do this? Would you please help me? thanks
You could generate integers via nextInt, and then divide them by the required power of 10.
Generate nextDouble(); and round it using this method
public static double round(double d, int decimalPlace){
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
double d = 3.1537;
// output is 3.2
System.out.println(d + " : " + round(d, 1));
// output is 3.15
System.out.println(d + " : " + round(d, 2));
// output is 3.154
System.out.println(d + " : " + round(d, 3));
Source
Multiply your number by 100 and round the result. That will give you the original number with the insignificant digits stripped off. Then subsequently divide the result by 100 to get back to the original scale.
x = Math.round(x*100.0) / 100.0;
If you want to use 2 decimals, you could do it as follows:
private static double[] randSum(int n, double m){
double[] randoms = new double[n];
int valueLeft = (int) (m * 100);
for(int i = 0; i < n-1; i++){
int tempRand = (int)(Math.random() * valueLeft);
randoms[i] = (double)tempRand / 100;
valueLeft -= tempRand;
System.out.println(tempRand + " " + randoms[i] + " " + valueLeft);
}
randoms[n-1] = (double)valueLeft/100;
return randoms;
}
Related
I need to display the correct arithmetic average of a series of integers entered by the user.
If the user enters 6, 9, 7, and 4, the average should be 6.5 but instead displays 6.0. Why does that happen? I used an ArrayList to store all the integers.
import java.util.Scanner;
import java.util.*;
import java.util.Collections;
public class QuizScoreStatistics
{
public static void main(String[] args) {
List<Integer> Scores = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
int i = 0;
int a = 0;
while(a != 99) {
System.out.println("Enter scores");
a = input.nextInt();
if(a != 99) {
if ( a > 10 || a < 0) {
System.out.println("Score must be between 10 and 0");
}
else {
Scores.add(a);
}
i++;
}
}
int max = Collections.max(Scores);
int min = Collections.min(Scores);
int sum = 0;
double averg = 0;
for( i = 0; i <= Scores.size() - 1; i++) {
sum += Scores.get(i);
}
averg = sum / Scores.size();
System.out.println("Scores entered " + i);
System.out.println("Highest score " + max);
System.out.println("Lowest score "+ min);
System.out.println("Average: "+ averg);
}
}
I won't try to give away the entire question I think you could probably answer that yourself given a nudge in the right direction.
You correctly identified that your averg is a double because your answer could come out to something like 6.7 or 2.3 or whatever. Thats a correct assumption to make! However during your "arithmetic process" you are using integers to do the division, which will come out as an integer. I will repeat the actual DIVISION is happening with two integers , can you see where the bug is coming from?
If you need more of a push to see the exact remedy of this solution I would point you here
https://programming.guide/java/wrong-results-for-division.html
Try averg = (1.0 *sum) / Scores.size(); because int/int => int but double/int=>double
Ok, this is how the operator "/" works.
int / int => int
int / float => float
float / int => float
Since you are doing an int division (int/int), the result will be an int, losing decimal information. If you want your division to be float or double, you have two options, either you declare the sum as double or you can just cast the division, so it becomes a double division instead of an int division.
averg = (double) sum / Scores.size();
I coded a very simple neural net with 1 neuron and 2 inputs and 1 bias in java, trying to classify dots on either the left or right side of a line. The problem is that the neural net recognizes the slope of the line but not the y-intercept (e.g. the function of the line may be y = m*x + c and the NN recognizes the m but not the c).
I tried to use a bias value=1 in order to enable the NN to calculate the weight for the bias which should be the y-intercept. But it doesnt. You will see that I am very new to Java programming. Unfortunately also new to NN. In that case I guess my problem is rather in the understanding of the underlying methodology of the bias in the NN.
Remark: In the output line at the very end of the code, I would expect in case of the function y = 3*x + 5 following figures: weight[0]=3 (which is the m) , weight[1]=1 (which is the factor for y) and weight[2]=5 (this is c). The weight[2] is always wrong.
package nn2;
public class anfang_eng {
public static void main(String[] args)
{
double[][] points = new double[5][10000];
double[] weights = new double[3];
double[][] normpoints = new double[5][10000];
// create 1000 dots with desired result for training afterwards
points = createPoints();
// the before randomly created x and y values of the 1000 dots
// shall be normalized between 0 and 1
normpoints = normalize(points);
// create two random initial weights
weights = createinitialWeights();
// training function, calculation of three different weights
calculateWeights(normpoints, weights);
testnewPoints(weights);
}
// thats the function of the line, that seperates all dots in
// two groups: all the dots at the left side of the line and all the dots
// at the right side.
static double function(double x, double y)
{
double result;
result = 3*x - y + 5;
return result;
}
static double[][] createPoints()
{
// 1. step: lets create for training reasons some dots and calculate
// the result for each dot (result is either "1" or "-1").
// point[0] is x, point[1] is y, point[2] is bias and point[3] is
// result (left or right side of the function above
int x;
int y;
int quantity= 1000;
double[][] point = new double[5][quantity];
for (int i=0; i<quantity; i++)
{
x = (int) (2000 * Math.random()-1000);
y = (int) (2000 * Math.random()-1000);
point[0][i] = x;
point[1][i] = y;
// point[2] is our bias
point[2][i] = 1;
// all dots which are at the right side of the function above get
// result "1". otherwise "-1"
if ( function(x,y) > 0)
point[3][i] = 1;
else
point[3][i] =-1;
// point[3] contains the result
}
// in the variable point, there are e.g. 1000 or 5000 dots with x, y,
// bias and the result (1=left side and -1=right side)
return point;
}
// normalize x and y values between 0 and 1
static double[][] normalize(double[][]points)
{
int quantity = points[0].length;
double minpoint_x=1000;
double minpoint_y=1000;
double maxpoint_x=-1000;
double maxpoint_y=-1000;
double[][] normpoints = new double[5][quantity];
minpoint_x= points[0][0];
minpoint_y = points[1][0];
maxpoint_x = points[0][0];
maxpoint_y = points[1][0];
for (int i=0; i<quantity;i++)
{
if (points[0][i]<minpoint_x)
minpoint_x=points[0][i];
if (points[1][i]<minpoint_y)
minpoint_y=points[1][i];
if (points[0][i]>maxpoint_x)
maxpoint_x=points[0][i];
if (points[1][i]>maxpoint_y)
maxpoint_y=points[1][i];
}
for (int u=0; u<quantity; u++)
{
normpoints [0][u]= (points[0][u]-minpoint_x)/(maxpoint_x-minpoint_x);
normpoints [1][u]= (points[1][u]-minpoint_y)/(maxpoint_y-minpoint_y);
normpoints [2][u] = 1; //bias is always 1
normpoints [3][u] = points[3][u];
}
return normpoints;
}
static double[] createinitialWeights()
{
// creation of initial weights between -1 and 1
double[] weight = new double[3];
weight[0] = 2*Math.random()-1;
weight[1] = 2*Math.random()-1;
weight[2] = 2*Math.random()-1;
return weight;
}
static void calculateWeights(double[][] normpoints, double[] weight)
// new weight = weight + error * input * learning constant
// c is learning constant
{
double c = 0.01;
double error = 0;
double sumguess = 0;
double guess = 0;
int quantity = normpoints[0].length;
for (int i=0; i < quantity; i++)
{
// normpoint[0][i] stands for the factor at x, normpoint[0][i] is
// for y and normpoint[2][i] is for bias
sumguess = normpoints[0][i] * weight[0] + normpoints[1][i]*weight[1] + normpoints[2][i]*weight[2];
if (sumguess > 0)
guess = 1;
else
guess = -1;
error = normpoints[3][i]- guess;
weight[0] = weight[0] + error * normpoints[0][i] * c;
weight[1] = weight[1] + error * normpoints[1][i] * c;
weight[2] = weight[2] + error * normpoints[2][i] * c;
System.out.println("i: " + i + " ;value_normpoint[0]:" + normpoints[0][i]+ " ;value_normpoint[1]" + normpoints[1][i]+ " ;value_normpoint[2]" + normpoints[2][i] + " result:" + normpoints[3][i]);
System.out.println("weight[0]: " + Math.round(weight[0]*100)/100.0 + " ;weight[1]: " +Math.round(weight[1]*100)/100.0 + " ;weight[2]: " + Math.round(weight[2]*100)/100.0 );
System.out.println("guess: "+ guess+ " result " + normpoints[3][i] + " error: " + error);
System.out.println();
}
System.out.println("final weights: x: " + weight[0] + " y: "+ weight[1] + " bias: " +weight[2]);
System.out.println("final weights normalized on y=1: x:" + weight[0]/weight[1] + " y: "+ weight[1]/weight[1] + " bias: " +weight[2]/weight[1]);
}
// lets test if the trained weights classify the test dot on the correct side of the line y=4*x+3
// again 500 random dots with "x", "y" and "results" are created and tested if the NN calculated correct weights
static void testnewPoints(double[] weights)
{
int x;
int y;
double[][] testpoint = new double[5][10000];
double[][] normalizedtestpoint = new double[5][10000];
int quantity = 500;
double sumcheck = 0;
double sumtest = 0;
int correct = 0;
int wrong = 0;
for (int i=0; i<quantity; i++)
{
// calculation of test points with x and y between -100 and 100
x = (int) (200 * Math.random()-100);
y = (int) (200 * Math.random()-100);
testpoint[0][i] = x;
testpoint[1][i] = y;
testpoint[2][i] = 1;
// lets classify the points: at the rights side of the line the result for each point is "1", on the left side "-1"
if (function(x,y) > 0)
testpoint[3][i] = 1;
else
testpoint[3][i] = -1;
// punkt[3] is the result
}
normalizedtestpoint= normalize(testpoint);
// are the test points with our calculated weights classified on the correct side of the line?
for (int i=0; i<quantity; i++)
{
sumcheck = normalizedtestpoint[0][i] * weights[0] + normalizedtestpoint[1][i] * weights[1] + normalizedtestpoint[2][i] * weights[2];
if (sumcheck > 0)
sumtest = 1;
else
sumtest = -1;
if (sumtest == normalizedtestpoint[3][i])
correct++;
else
wrong++;
}
System.out.println("correct: "+ correct + " wrong: " + wrong);
}
}
Please let me also know if you see some major issues in my coding style, quite an beginner style I guess.
Many thanks in advance!
Lonko
Can someone help me for geting out this code of sin(x) Tailor function to get followings:
The first 4 sin(x) Tailor series.
To calculating the sin function using the sum-formel
How to write a method public static double MySinApproximate( double x)?
That is what i get so far, and it has to be in this way!!
import java.lang.Math;
public class mysin {
public static void main(String[] args){
double x= Math.PI;
System.out.println( MySin(x) + "\t \t" + Math.sin(x) + "\n" );
}
public static double MySin(double x){
double sumNeu, sumOld, sum;
int i = 1;
sum = sumNeu = x; // This should calculating the first term Value
do //the loop do will calculating the Tailor Series
{
sumOld = sumNeu;
i++; sum = + sum * x * x / i;
i++; sum = sum / i;
sumNeu = sumOld + sum;
}
while( sumNeu != sumOld);
return sumNeu;
}
} // 11.548739357257745 1.2246467991473532E-16 (as output)
Your loop isn't calculating the Taylor series correctly. (This is really a Maclaurin series, which is the special case of a Taylor series with a = 0.) For the sine function, the terms need to be added and subtracted in an alternating fashion.
sin(x) = x - x3/3! + x5/5! - ...
Your method only adds the terms.
sin(x) = x + x3/3! + x5/5! + ...
Flip the sign of sum on each iteration, by adding the designated line:
do // The loop will calculate the Taylor Series
{
sumOld = sumNeu;
i++; sum = + sum * x * x / i;
i++; sum = sum / i;
sum = -sum; // Add this line!
sumNeu = sumOld + sum;
}
With this change I get a result that is very close:
2.3489882528577605E-16 1.2246467991473532E-16
Due to the inherent inaccuracies of floating-point math in Java (and IEEE in general), this is likely as close as you'll get by writing your own sine method.
I tested an additional case of π/2:
System.out.println( MySin(x/2) + "\t \t" + Math.sin(x/2) + "\n" );
Again, it's close:
1.0000000000000002 1.0
1.I want to write all again like that -
2.I try to writing the first 4 series from sine Taylor and the proximity all together but anyhow doesn't work correctly -
3.i get this output
0.0 0.8414709848078965
0.8414709848078965 0.9092974268256817
0.8414709848078965 0.1411200080598672
0.9092974268256817 -0.7568024953079282
4.How can i get the same accuracy
1.0000000000000002 1.0
and the series of sine(x)?
public class MySin {
public static void main(String[] args){
double y = 0;
y = 4;
for (int i = 1; i<= y; i++){
System.out.println( MySin(i/2) + "\t \t" + Math.sin(i) + "\n" );
}
}
public static double MySin(double x){
double sumNew, sumOld, sum;
int i = 1;
sum = sumNew = x; // This should calculating the first term Value
do //the loop do will calculating the Tailor Series
{
sumOld = sumNew;
i++; sum = - sum * x * x / i; // i did change the sign to -
i++; sum = sum / i;
sum = - sum; // so i don't need this line anymore
sumNew = sumOld + sum;
}
while( sumNew != sumOld);
return sumNew;
}
public static double MySineProximity ( double x) {
while ( x <= ( Math.PI /2 ) )
{
x = 0;
}
return MySin (x);
}
}
I'm looking for some method that takes or does not take parameters for calculate confidence interval.
I don't want the apache methods,
just a simple method or som type of code that does this.
My knowledge is restricted, it basically boils down to completing an online task against an expected set of answers (https://www.hackerrank.com/challenges/stat-warmup).
However, as far as I read up, there are mistakes in the given answer, and I'd like to correct these.
My source is pretty much wikipedia https://en.wikipedia.org/wiki/Confidence_interval#Basic_Steps
/**
*
* #return int[]{lower, upper}, i.e. int array with Lower and Upper Boundary of the 95% Confidence Interval for the given numbers
*/
private static double[] calculateLowerUpperConfidenceBoundary95Percent(int[] givenNumbers) {
// calculate the mean value (= average)
double sum = 0.0;
for (int num : givenNumbers) {
sum += num;
}
double mean = sum / givenNumbers.length;
// calculate standard deviation
double squaredDifferenceSum = 0.0;
for (int num : givenNumbers) {
squaredDifferenceSum += (num - mean) * (num - mean);
}
double variance = squaredDifferenceSum / givenNumbers.length;
double standardDeviation = Math.sqrt(variance);
// value for 95% confidence interval, source: https://en.wikipedia.org/wiki/Confidence_interval#Basic_Steps
double confidenceLevel = 1.96;
double temp = confidenceLevel * standardDeviation / Math.sqrt(givenNumbers.length);
return new double[]{mean - temp, mean + temp};
}
here is you go this is the code calculate Confidence Interval
/**
*
* #author alaaabuzaghleh
*/
public class TestCI {
public static void main(String[] args) {
int maximumNumber = 100000;
int num = 0;
double[] data = new double[maximumNumber];
// first pass: read in data, compute sample mean
double dataSum = 0.0;
while (num<maximumNumber) {
data[num] = num*10;
dataSum += data[num];
num++;
}
double ave = dataSum / num;
double variance1 = 0.0;
for (int i = 0; i < num; i++) {
variance1 += (data[i] - ave) * (data[i] - ave);
}
double variance = variance1 / (num - 1);
double standardDaviation= Math.sqrt(variance);
double lower = ave - 1.96 * standardDaviation;
double higher = ave + 1.96 * standardDaviation;
// print results
System.out.println("average = " + ave);
System.out.println("sample variance = " + variance);
System.out.println("sample standard daviation = " + standardDaviation);
System.out.println("approximate confidence interval");
System.out.println("[ " + lower + ", " + higher + " ]");
}
}
This question already has answers here:
Java: Inaccuracy using double [duplicate]
(4 answers)
Closed 9 years ago.
I am getting strange output when I add doubles together. Can someone tell me why I'm getting repeating decimals when I am adding 0.1 every time?
I have worked out the formula for adding these numbers together and I have done this myself on paper up to 3.3... The sum of all numbers (decreasing by 1 tenth) from 3.3 to 1 equals 51.6
3.3
3.2
3.1 +
3.0
...
1.0
_
51.6
There is an easier way to calculate this using two formulas:
The linear formula for the increasing number: Y = 0.1X + 1
And the sum of increasing numbers formula: [X * (Y + 1)]/2 = total
first solve for Y using any number (in this case 100)
11 = 0.1(100) + 1
Then solve for the total using X and Y
[100 * (11+1)]/2 = 600
The output of the following code should be 600 I believe. There is no question that it should not have a repeating decimal. What am I doing wrong here? There must be something I missed.
public static void main(String[] args) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Double does not have infinite precision (Neither does BigDecimal, but BigDecimal has sufficient precision for this implementation).
Try this,
public static void main(String[] args) {
int days = 100;
java.math.BigDecimal init = java.math.BigDecimal.ONE;
java.math.BigDecimal total = java.math.BigDecimal.ZERO;
java.math.BigDecimal oneTenth = new java.math.BigDecimal(
"0.1");
for (int i = 1; i <= days; i++) {
if (i != 1) {
init = init.add(oneTenth);
}
total = total.add(init);
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Which outputs
Total: 595.0
Daily: 10.9
Please read the link that Don Roby posted. In essence, double precision is not a good way to represent fractions. A number like 0.1 does not have an exact representation in binary float notation - because floating point numbers are written as "something times two to the power something else". And you cannot solve that exactly for 0.1. Thus, you are really getting a slightly smaller number - actually
0.0999999999999998
And that missing amount is enough to mess up the math…
See Jon Skeet's very excellent answer on this topic: https://stackoverflow.com/a/1089026/1967396
The formula should be
0.1 * (100 * (100 + 1) / 2)
except you start at 10 * 0.1 so the formula is more complicated.
In any case double precision is not exact esp for numbers like 0.1, so you should expect to get rounding error.
You can work around this by using numbers which can be represented accurately like 1 instead of 0.1 (or rounding the result)
public static void main(String... ignored) {
int days = 100;
double inc = 1;
double init = 10;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
total /= 10;
init /= 10;
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
or round the result.
public static void main(String... ignored) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.printf("Total: %.1f%n", total);
System.out.printf("Daily: %.1f%n", init);
}
both print
Total: 595.0
Daily: 10.9