I have this method:
public double sineWave(double t)
{
return amplitude==0?0:Math.sin(t * frequency * Math.PI*2 + phase) * amplitude;
}
It is called by another method in another class to generate a sample of a simple sine wave, which is then added in a buffer to send to the sound card. t is the time. For some reason, the more the application calls this method, the slower it gets. It just makes no sense, after 15 seconds it's slow enough to use a full core of my CPU and make the audio stutter.
I'm 100% sure it's this piece of code, because if I replace it with a return 0, the time it takes to run it (measured with System.nanotime()) is constant.
Why is this happening? Is there something I can do to fix this?
From the information here - while it is not clear how big your buffer is, you are incrementing t with each iteration. Assuming your frequency is quite high, you are increasing the Sin() argument with each iteration.
Have checks to see if the argument is constantly increasing to a very high value.
A quick and dirty test shows that Sin performance goes down -
public class SinTest {
public static void main(String args[]) {
long angle = Long.parseLong(args[0]);
long startTime = System.nanoTime();
for(long l=0L; l<=1000000L; l++) {
Math.sin(angle);
}
long estimatedTime = System.nanoTime() - startTime;
System.out.println(estimatedTime);
}
}
$ java SinTest 100000
29181000
$ java SinTest 10000000
138598000
Please give no points, so the solution would be given the answer of #mk:
public double sineWave(double t)
{
final double TAU = Math.PI *2;
double a = t * frequency;
a -= (long)a;
return amplitude==0?0:Math.sin(a * TAU + phase) * amplitude;
}
i solved the problem with a lookup table:
private static final int LUT_SIZE=1000000;
private static double[] sineLookupTable=new double[(int)(Math.PI*2*LUT_SIZE)];
static{
for(double i=0;i<sineLookupTable.length;i++){
sineLookupTable[(int)i]=Math.sin(i/(double)LUT_SIZE);
}
}
private static double sinLUT(double t){
return sineLookupTable[(int) (((long) Math.floor((t%Math.PI*2)*LUT_SIZE))%sineLookupTable.length)];
}
public double sineWave(double t) {
return amplitude==0?0:sinLUT(t * frequency * Math.PI*2 + phase) * amplitude;
}
it works... kinda, only problem is that i get a lot of distorsion on high frequencies. is there some interpolation method you can suggest?
Current versions of the Java framework will attempt to mod-reduce the argument to Math.sin using a mathematically-perfect value of 2π, rather than the value Math.PI*2. For code such as yours, this means the code will take longer and yield less accurate results than if mod reduction had been performed using the same scale factor as was used in multiplication (i.e. Math.PI*2). To get good accuracy and speed, you should perform modulo reduction before doing the multiplication, using something like:
double thisSpin = t * frequency;
thisSpin -= (thisSpin - Math.Floor(thisSpin)) * 8.0; // value of 0-7.9999=one rotation
switch((int)(thisSpin*8.0))
{
case 0: return Math.sin( thisSpin * (Math.PI/4.0));
case 1: return Math.cos((2-thisSpin) * (Math.PI/4.0));
case 2: return Math.cos((thisSpin-2) * (Math.PI/4.0));
case 3: return Math.sin((4-thisSpin) * (Math.PI/4.0));
case 4: return -Math.sin((thisSpin-4) * (Math.PI/4.0));
case 5: return -Math.cos((6-thisSpin) * (Math.PI/4.0));
case 6: return -Math.cos((thisSpin-6) * (Math.PI/4.0));
case 7: return -Math.sin((8-thisSpin) * (Math.PI/4.0));
default: return 0; // Shouldn't be possible, but thisSpin==8 would be congruent to 0
}
That will ensure that neither sin nor cos is ever used with an argument greater than π/4, which is according to the documentation the point where Java switches to using slow and counterproductive range reduction.
Related
I am having a little issue with formatting returned methods in the main method. I have created the methods and done the calculation, but my issue is if i am calling the other two methods to the main method correctly. I am also having and issue with formatting each method in columns. Do i need to make the columns in the respected methods? or do i need to create them in the main method?
Write a program that analyzes an object falling for 10 seconds. It should contain main and two additional methods. One of the additional methods should return the distance an object falls in meters when passed the current second as an argument. See the formula needed below. The third method should convert meters to feet. You can look up the conversion factor needed online. The main method should use one loop to call the other methods and generate a table as shown below. The table should be displayed in formatted columns with decimals as shown. I believe i am on
SEC METERS FEET
1 4.9 16.1
2 19.6 64.3
3 44.1 144.7
4 78.4 257.2
5 122.5 401.9
6 176.4 578.7
7 240.1 787.7
8 313.6 1028.9
9 396.9 1302.2
10 490.0 1607.6
My code
package week4.yedkois;
public class project3 {
public static void main(String[] args) {
System.out.printf("SEC" + "\n");
meters();
feet();
for (int time = 1; time <= 10; time++) {
System.out.println(time);
}
}
public static void meters() {
double Meters;
double G = 9.8; // meters = .5(9.8)(seconds) ^2
for (int time = 1; time <= 10; time++) {
Meters = (.5 * 9.8 * Math.pow(time, 2));
System.out.printf("%.1f\n", Meters);
}
return;
}
public static void feet() {
double Feet;
double G = 9.8; // meters = .5(9.8)(seconds) ^2
for (int time = 1; time <= 10; time++) {
Feet = (.5 * 9.8 * Math.pow(time, 2) * 3.28084);
System.out.printf("%.1f\n", Feet);
}
return;
}
}
Here is my solution. I use a Tab ("\t") to achieve the same space between the different values. And then I had to redesign your code a little. I use only one if-loop directly in the main-method and hand the current time-value as a parameter into both methods meters() and feet(). That makes it much easier to get all values of one round in line.
Here are some additional remarks:
Java is not C++, so you don't have to use an empty return statement at the end of a method. It's useless there.
In Java variables and method-names always start with a small letter, _ or $. Only class-names and constants start with a capital letter.
Hope this helps for a start.
public class Project3 {
public static void main(String[] args){
System.out.printf("%3s\t%6s\t%6s\n", "SEC", "METERS", "FEET");
for(int time = 1; time <= 10; time++)
{
System.out.print(time + "\t");
meters(time);
feet(time);
System.out.println();
}
}
public static void meters(int time){
double meters;
double g = 9.8; // meters = .5(9.8)(seconds) ^2
meters = (.5 * 9.8 * Math.pow(time, 2));
// the longer the expected maximum length of a result gets
// the higher your reserved number of digits has
// to be, to gain the wanted right bound effect!
System.out.printf("%6.1f\t", meters);
}
public static void feet(int time){
double feet;
double g = 9.8; // meters = .5(9.8)(seconds) ^2
feet = (.5 * 9.8 * Math.pow(time, 2) * 3.28084);
// the longer the expected maximum length of a result gets
// the higher your reserved number of digits has
// to be, to gain the wanted right bound effect!
System.out.printf("%6.1f", feet);
}
}
I am encountering a problem when creating a program to solve simple kinematics.
I run the program and find out the fields haven't been modified properly . Here is
the scrap of my program that initialise the object and setting the variables.
public class LinearConstantAcceleration1DKinematics {
private double distance;
private double speed;
private double acceleration;
private double time;
public LinearConstantAcceleration1DKinematics() {
/* initialize the object */
distance = 0;
speed = 0;
acceleration = 0;
time = 0;
}
public void setS(double s) {
this.distance = s;
}
//continue with 3 more setters which is created in the same way ,i have omitted them here
public double getU(){
double u_ans;
u_ans = (distance - 1/2 *acceleration*time*time )/time;
return u_ans;
}
}
And here is the main that uses the methods
LinearConstantAcceleration1DKinematics kinematics = new LinearConstantAcceleration1DKinematics();
kinematics.setS(175);
kinematics.setA(10);
kinematics.setT(5);
System.out.printf(%f\n", kinematics.getU());
The result is 35 which is incorrect.Many thanks for your help.
This has absolutely nothing to do with setter methods -- your division is wrong since 1 / 2 does int division and returns 0 resulting in the equation calculating simply distance / time.
Change to:
u_ans = (distance - 1.0 / 2.0 * acceleration * time * time) / time;
Lesson to learn: don't assume where the error is -- test it. Use a debugger or println statements to check the states of your variables as your program runs.
I was doing some arithmetic program today and I got a real funny result passing the result of float division to a setter :
class A {
Float f;
setF(Float f) {
this.f=f;
print (f)
}
}
Long x=7L;
Long y=3L;
print (x/y.floatValue() )
a.setF(x/y.floatValue());
the result of the above pseudo program is something like this in the jdk 1.6
2.333333
2.0
any clue on where the round is performed?
Let me explain your first condition i.e. `x/y.floatValue()' what you are doing is:
long/ float because you are taking float value from variable y from floatValue() method so according to its implementation, you will get y = 3.0F.
/**
* Returns the value of this {#code Long} as a
* {#code float}.
*/
public float floatValue() {
return (float)value;
}
Your division will be 7L/ 3F or say 7/ 3.0 which will give you the result as 2.333333
Your second condition a.setF(x/y.floatValue()); will also result 2.333333 check if you missed something or post your whole code.
As you can see in console header I am using JDK1.6
It's a casting issue. Your x is still type long, whereas y.floatValue() is a float.
Both the divisor and the dividend need to be float or double to get what you want, so try for example, this:
Long x=7L;
Long y=3L;
System.out.println((float) x/(float) y);
result -> 2.3333333
This rounding down to 2.0 does not happen, there may be a problem with how you wrote the code from that pseudo-code
I tested with this implementation
public class A {
Float f;
void setF(Float f){
this.f=f;
System.out.println(f);
}
public static void main(String[] args) {
Long x=7L;
Long y=3L;
System.out.println(x/y.floatValue());
new A().setF(x/y.floatValue());
}
}
This is the result
2.3333333
2.3333333
java.util.Random.nextDouble() is slow for me and I need something really fast.
I did some google search and I've found only integers based fast random generators. Is here anything for real numbers from interval <0, 1) ?
If you need something fast and have access to Java8, I can recommend the java.utils SplittableRandom. It is faster (~twice as fast) and has better statistical distribution.
If you need a even faster or better algorithm I can recommend one of these specialized XorShift variants:
XorShift128PlusRandom (faster & better)
XorShift1024StarPhiRandom (similar speed, even longer period)
Information on these algorithms and their quality can be found in this big PRNG comparison.
I made an independent Performance comparison you can find the detailed results and the code here: github.com/tobijdc/PRNG-Performance
Futhermore Apache Commons RNG has a performance test of all their implemented algoritms
TLDR
Never use java.util.Random, use java.util.SplittableRandom.
If you need faster or better PRNG use a XorShift variant.
You could modify an integer based RNG to output doubles in the interval [0,1) in the following way:
double randDouble = randInt()/(RAND_INT_MAX + 1.0)
However, if randInt() generates a 32-bit integer this won't fill all the bits of the double because double has 53 mantissa bits. You could obviously generate two random integers to fill all mantissa bits. Or you could take a look at the source code of the Ramdom.nextDouble() implementation. It almost surely uses an integer RNG and simply converts the output to a double.
As for performance, the best-performing random number generators are linear congruential generators. Of these, I recommend using the Numerical Recipes generator. You can see more information about LCGs from Wikipedia: http://en.wikipedia.org/wiki/Linear_congruential_generator
However, if you want good randomness and performance is not that important, I think Mersenne Twister is the best choice. It also has a Wikipedia page: http://en.wikipedia.org/wiki/Mersenne_Twister
There is a recent random number generator called PCG, explained in http://www.pcg-random.org/. This is essentially a post-processing step for LCG that improves the randomness of the LCG output. Note that PCG is slower than LCG because it is simply a post-processing step for LCG. Thus, if performance is very important and randomness quality not that important, you want to use LCG instead of PCG.
Note that none of the generators I mentioned are cryptographically secure. If you need use the values for cryptographical applications, you should be using a cryptographically secure algorithm. However, I don't really believe that doubles would be used for cryptography.
Note that all these solutions miss a fundamental fact (that I wasn't aware of up to a few weeks ago): passing from 64 bits to a double using a multiplication is a major loss of time. The implementation of xorshift128+ and xorshift1024+ in the DSI utilities (http://dsiutils.di.unimi.it/) use direct bit manipulation and the results are impressive.
See the benchmarks for nextDouble() at
http://dsiutils.di.unimi.it/docs/it/unimi/dsi/util/package-summary.html#package.description
and the quality reported at
http://prng.di.unimi.it/
Imho you should just accept juhist's answer - here's why.
nextDouble is slow because it makes two calls to next() - it's written right there in the documentation.
So your best options are:
use a fast 64 bit generator, convert that to double (MT, PCG, xorshift*, ISAAC64, ...)
generate doubles directly
Here's an overly long benchmark with java's Random, an LCG (as bad as java.util.Random), and Marsaglia's universal generator (the version generating doubles).
import java.util.*;
public class d01 {
private static long sec(double x)
{
return (long) (x * (1000L*1000*1000));
}
// ns/op: nanoseconds to generate a double
// loop until it takes a second.
public static double ns_op(Random r)
{
long nanos = -1;
int n;
for(n = 1; n < 0x12345678; n *= 2) {
long t0 = System.nanoTime();
for(int i = 0; i < n; i++)
r.nextDouble();
nanos = System.nanoTime() - t0;
if(nanos >= sec(1))
break;
if(nanos < sec(0.1))
n *= 4;
}
return nanos / (double)n;
}
public static void bench(Random r)
{
System.out.println(ns_op(r) + " " + r.toString());
}
public static void main(String[] args)
{
for(int i = 0; i < 3; i++) {
bench(new Random());
bench(new LCG64(new Random().nextLong()));
bench(new UNI_double(new Random().nextLong()));
}
}
}
// straight from wikipedia
class LCG64 extends java.util.Random {
private long x;
public LCG64(long seed) {
this.x = seed;
}
#Override
public long nextLong() {
x = x * 6364136223846793005L + 1442695040888963407L;
return x;
}
#Override
public double nextDouble(){
return (nextLong() >>> 11) * (1.0/9007199254740992.0);
}
#Override
protected int next(int nbits)
{
throw new RuntimeException("TODO");
}
}
class UNI_double extends java.util.Random {
// Marsaglia's UNIversal random generator extended to double precision
// G. Marsaglia, W.W. Tsang / Statistics & Probability Letters 66 (2004) 183 – 187
private final double[] U = new double[98];
static final double r=9007199254740881.0/9007199254740992.;
static final double d=362436069876.0/9007199254740992.0;
private double c=0.;
private int i=97,j=33;
#Override
public double nextDouble(){
double x;
x=U[i]- U[j];
if(x<0.0)
x=x+1.0;
U[i]=x;
if(--i==0) i=97;
if(--j==0) j=97;
c=c-d;
if(c<0.0)
c=c+r;
x=x-c;
if(x<0.)
return x+1.;
return x;
}
//A two-seed function for filling the static array U[98] one bit at a time
private
void fillU(int seed1, int seed2){
double s,t;
int x,y,i,j;
x=seed1;
y=seed2;
for (i=1; i<98; i++){
s= 0.0;
t=0.5;
for (j=1; j<54; j++){
x=(6969*x) % 65543;
// typo in the paper:
//y=(8888*x) % 65579;
//used forthe demo in the last page of the paper.
y=(8888*y) % 65579;
if(((x^y)& 32)>0)
s=s+t;
t=.5*t;
}
if(x == 0)
throw new IllegalArgumentException("x");
if(y == 0)
throw new IllegalArgumentException("y");
U[i]=s;
}
}
// Marsaglia's test code is useless because of a typo in fillU():
// x=(6969*x)%65543;
// y=(8888*x)% 65579;
public UNI_double(long seed)
{
Random r = new Random(seed);
for(;;) {
try {
fillU(r.nextInt(), r.nextInt());
break;
} catch(Exception e) {
// loop again
}
}
}
#Override
protected int next(int nbits)
{
throw new RuntimeException("TODO");
}
}
You could create an array of random doubles when you init your program and then just repeat it. This is much faster but the random values reapeat themselfs.
Still learning and I cant seem to wrap my head on what seemed like an easy task.
The computeMethods method's is where im totaly stumped, however the reverse method i just keep getting back the same integer without it being reversed.
/****************************
* For Method Computemethods1 i must compute series
* b(x)=1/3+2/5+3/7..... +x/2x+1
* For method ComputeMethod2
* 1/2+2/3+......... x/(x+1)
*******************************/
public static int computeMethod1(int x){
if (x==0)
return 0;
if (x==1)
return 1;
return computeMethod1(x-1/3/(x-1))+computeMethod1(x-2/3/(x-2));
}
public static int computeMethod2(int x){
if (x==0)
return 0;
return computeMethod2((x-1)/(x-1)+1)+computeMethod2((x-2)/(x-2)+1);
}
/********************
* For method reverseMethod i must reverse a user given int
**********************/
public static int reverseMethod(int x){
int reversedNum=0;
if (x!=0)
return x;
reversedNum=reversedNum *10 +x%10;
return reversedNum+reverseMethod(x/10);
}
/******************
* For method sumDigits i must use recursion
* to sum up each individual number within the int
********************/
public static long sumDigits(long n){
if( n==0)
return 0;
if (n==1)
return 1;
else
return n+sumDigits(n-1);
}
}
For reverse method, you are using: if (x!=0) return x;
May be you need to use: if (x==0) return x. So the logic is, if the given argument is 0, then return 0, else return reversed number.
P.S.: As somebody mentioned in comentaries, please take care of types, so for the division you are better using float or double, and take care of operations precedence for correct result, so (x+1)/2 will be different from x+1/2.
For each of your methods, follow through your code for small x.
For example, computeMethod1 should return:
1/3 for x == 1, whereas at the moment it simply returns 1 (Note, the return type will need to be something other than int.).
1/3 + 2/5 for x == 2.
1/3 + 2/5 + 3/7 for x == 3.
For each x, notice how we can use the previous result i.e. computeMethod1(x - 1).
When you come across code that doesn't seem to do what you expect, make your code simpler and simpler until you can narrow down where the problem is, then hopefully it will be obvious what the problem is, or online documentation can tell you.