1000000000 nanoseconds do not appear to equal a second - java

I am creating some magic spells, and obviously I want a delay between each usage.
Now According to google, there are 1000000000 nanoseconds in a second.
However, the magic spell is recharging after less than two seconds.
#EventHandler
public void onInteract(PlayerInteractEvent e){
Player p = e.getPlayer();
if (p.getItemInHand().getType().equals(Material.BLAZE_ROD)){
{
{
if (!kam.containsKey(p.getName())) kam.put(p.getName(), (long) 0);
if (kam.get(p.getName()) < System.nanoTime()){
kam.remove(p.getName());
kam.put(p.getName(), System.nanoTime() + (1000000000 * 30));
//Do magic spell attack here.
}
}
}else{
p.sendMessage(ChatColor.AQUA + "Skill recharging!");
}
}
Obviously my code is trying to add the System.nanoTime() plus 30 seconds, and then checking if the current system nanoTime is greater than the one I put into the hashmap, and if it is, do the spell.

I suggest you print out the value 1000000000 * 30 and check it. You'll find it's wrapping around because it's too big to fit into an integer.
In other words, the following program:
public class Test
{
public static void main(String args[])
{
System.out.println(1000000000 * 30);
System.out.println(1000000000L * 30);
}
}
prints out:
-64771072
30000000000
So, if you use the long variant, it will work fine.

bare numeric literals in Java are treated as ints, and thus your calculation overflows. One way to fix this is to perform the calculation with long literals, by adding L after the literal:
kam.put(p.getName(), System.nanoTime() + (1000000000L * 30L));

Related

How to run a For Loop for 60 seconds maximum irrespective of the size of the loop and complete all the iterations

for(i=1;i<list.size();i++){
//do something
//For Eg: move marker to a new position on the map
}
I want the above loop to complete all the iterations irrespective of the size of the list and also want the entire task to run for 1 minute. (60 seconds)
I don't really know if this is what you want but I hope this helps.
import java.util.concurrent.TimeUnit;
for(i=1;i<list.size();i++){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute thing you want to be executed every second
}
As explanation: you iterate through the for loop and the thread waits for one second before executing the code after the TimeUnit.SECONDS.sleep(1);.
If the list's size is 60 it would therefore take a minute for the loop to end.
Edit: It has occurred to me that it might be smarter to do a try-catch around the sleep function.
You can, for example, use System.nanoTime() to measure the duration of your loop, and then use TimeUnit.NANOSECONDS.sleep(...) to make it wait for the rest of time like this:
long start = System.nanoTime();
long desiredDuration = 60 * 1000 * 1000;
// your loop goes here
long duration = System.nanoTime() - start;
if (duration < desiredDuration)
TimeUnit.NANOSECONDS.sleep(desiredDuration - duration);
The best possible solution is to compute the desired time first and then run the loop to that extent.
long finish=System.currentTimeMillis() + 60000;
while(System.currentTimeMillis() != finish)
{
//statements;
//statements;
}
If you are trying to equip the CPU and keep it idle for this time the process is known as busy waiting but is not considered convenient in many cases so i recommend to use Thread.sleep(duration) for this purpose.
Would like to receive further queries from your side.
To spread N amount of invocations uniformly across a minute, you'll have to set the delay in between the invocations to the value 60/(N-1). The -1 is optional but causes the first and last invocations to be exactly 60 seconds apart. (just like how a ladder with N rungs has N-1 spaces)
Of course, using sleep() with the number calculated above is not only subject to round-off errors, but also drift, because you do stuff between the delays, and that stuff also takes time.
A more accurate solution is to subtract the time at which each invocation should occur (defined by startTime + 60*i/(N-1)) from the current time. Reorder and reformulate those formulas and you can subtract the 'time that should have elapsed for the next invocation' from the already elapsed time.
Of course 'elapsed time' should be calculated using System.nanoTime() and not System.currentTimeMillis() as the latter can jump when the clock changes or the computer resumes from stand-by.
For this example I changed 60 seconds to 6 seconds so you can more easily see what's going on when you run it.
public static void main(String... args) throws Exception {
int duration = 6; // seconds
List<Double> list = IntStream.range(0, 10).mapToDouble(i->ThreadLocalRandom.current().nextDouble()).boxed().collect(Collectors.toList());
long startTime = System.nanoTime();
long elapsed = 0;
for (int i = 0; i < list.size(); i++) { // Bug fixed: start at 0, not at 1.
if (i > 0) {
long nextInvocation = TimeUnit.NANOSECONDS.convert(duration, TimeUnit.SECONDS) * i / (list.size() - 1);
long sleepAmount = nextInvocation - elapsed;
TimeUnit.NANOSECONDS.sleep(sleepAmount);
}
elapsed = System.nanoTime() - startTime;
doSomething(elapsed, list.get(i));
}
}
private static void doSomething(long elapsedNanos, Double d) {
System.out.println(elapsedNanos / 1.0e9f + "\t" + d);
}
Of course when the task you preform per list element takes longer than 60/(N-1) seconds, you get contention and the 'elapsed time' deadlines are always exceeded. With this algorithm the total time just taking longer than a mnute. However if some earlier invocations exceed the deadline, and later invocations take much less time than 60/(N-1), this algorithm will show 'catch-up' behavior. This can be partially solved by sleeping at least a minimum amount even when sleepAmount is less.
Check out this.
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
int i = 0;
while (System.currentTimeMillis() < end)
{
// do something, iterate your list
i++;
if (i == list.size()) { // check size of the list if iteration is completed
// if time has not yet expired, sleep for the rest of the time
Thread.sleep(end - System.currentTimeMillis());
}
}
Do not forget checking size of the list.

Why is my java program becoming gradually slower?

I recently built a Fibonacci generator that uses recursion and hashmaps to reduce complexity. I am using the System.nanoTime() to keep track of the time it takes for my program to print 10000 Fibonacci number. It started out good with less than a second but gradually became slower and now it takes more than 4 seconds. Can someone explain why this might be happening. The code is down here-
import java.util.*;
import java.math.*;
public class FibonacciGeneratorUnlimited {
static int numFibCalls = 0;
static HashMap<Integer, BigInteger> d = new HashMap<Integer, BigInteger>();
static Scanner fibNumber = new Scanner(System.in);
static BigInteger ans = new BigInteger("0");
public static void main(String[] args){
d.put(0 , new BigInteger("0"));
d.put(1 , new BigInteger("1"));
System.out.print("Enter the term:\t");
int n = fibNumber.nextInt();
long startTime = System.nanoTime();
for (int i = 0; i <= n; i++) {
System.out.println(i + " : " + fib_efficient(i, d));
}
System.out.println((double)(System.nanoTime() - startTime) / 1000000000);
}
public static BigInteger fib_efficient(int n, HashMap<Integer, BigInteger> d) {
numFibCalls += 1;
if (d.containsKey(n)) {
return (d.get(n));
} else {
ans = (fib_efficient(n-1, d).add(fib_efficient(n-2, d)));
d.put(n, ans);
return ans;
}
}
}
If you are restarting the program every time you make a new fibonacci sequence, then your program most likely isn't the problem. It might just be the your processor got hot after running the program a few times, or a background process in your computer suddenly started, causing your program to slow down.
More memory java -Xmx=... or less caching
public static BigInteger fib_efficient(int n, HashMap<Integer, BigInteger> d) {
numFibCalls++;
if ((n & 3) <= 1) { // Every second is cached.
BigInteger cached = d.get(n);
if (cached != null) {
return cached;
} else {
BigInteger ans = fib_efficient(n-1, d).add(fib_efficient(n-2, d));
d.put(n, ans);
return ans;
}
} else {
return fib_efficient(n-1, d).add(fib_efficient(n-2, d));
}
}
Two subsequent numbers are cached out of four in order to stop the
recursion on both branches for:
fib(n) = fib(n-1) + fib(n-2)
BigInteger isn't the nicest class where performance and memory is concerned.
It started out good with less than a second but gradually became slower and now it takes more than 4 seconds.
What do you mean by this? Do you mean that you ran this exact same program with the same input and its run-time changed from < 1 second to > 4 seconds?
If you have the same exact code running with the same exact inputs in a deterministic algorithm...
then the differences are probably external to your code - maybe other processes are taking up more CPU on one run.
Do you mean that you increased the inputs from some value X to 10,000 and now it takes > 4 seconds?
Then that's just a matter of the algorithm taking longer with larger inputs, which is perfectly normal.
recursion and hashmaps to reduce complexity
That's not quite how complexity works. You have improved the best-case and the average-case, but you have done nothing to change the worst-case.
Now for some actual performance improvement advice
Stop printing out the results... that's eating up over 99% of your processing time. Seriously, though, switch out "System.out.println(i + " : " + fib_efficient(i, d))" with "fib_efficient(i,d)" and it'll execute over 100x faster.
Concatenating strings and printing to console are very expensive processes.
It happens because the complexity for Fibonacci is Big-O(n^2). This means that, the larger the input the time increases exponentially, as you can see in the graph for Big-O(n^2) in this link. Check this answer to see a complete explanation about it´s complexity.
Now, the complexity of your algorithm increases because you are using a HashMap to search and insert elements each time that function is invoked. Consider remove this HashMap.

Why are all my times currenttimeMillis() the same?

So I have started using System.currentTimeMillis(); I am trying to test the results between two of my methods. I decided to gut my method so that what it does doesn't get in the way. Basically I am not seeing any change in time. I have something like this:
double start= System.currentTimeMillis();
double end=System.currentTimeMillis();
public void displayMethod()
{
System.out.println("The start time is" + start);
for (ITERATIONS AND STUFF)
{
System.out.format(STUFF BEING PRINTED);
}
System.out.println("The end time is" + end);
double difference = start-end;
System.out.println("The difference " + difference);
}
The idea is that I have a start time, the time between every print out of the statement and the time at the end. Then it is subtracted to show the difference. However there is no difference and all the times are the same. Why is this happening?
I am considering using nanotime but I don't really know how to use that and I have heard that it takes performance hits.
Can anyone tell me why my times are the same and suggest a way to
fix it or give me an alternative route that is suitable gets the
answer?
You're capturing all of the times at the beginning with these lines:
double thetime= System.currentTimeMillis();
double start= System.currentTimeMillis();
double end=System.currentTimeMillis();
You're getting the same times because those lines are executed immediately back to back (and are fast calls so likely happen in less than 1ms)
Adjust your code to:
public void displayMethod()
{
long start= System.currentTimeMillis();
System.out.println("The start time is" + start);
for (ITERATIONS AND STUFF)
{
System.out.format(STUFF BEING PRINTED);
System.out.println(System.currentTimeMillis());
}
long end=System.currentTimeMillis();
System.out.println("The end time is" + end);
double difference = end-start;
System.out.println("The difference " + difference);
}
Notice how the declarations of the variables are moved to the places that they are needed. It's important to note that variable assignment happens at declaration time not at usage time, thus it's important to move the calls to System.currentTimeMillis() to the point at which you want to capture the current time.
Side note: I adjusted the variables to long instead of double, as System.currentTimeMillis() returns a long and there's no reason for a double here.
You are getting all the times at the very beginning. You need to call System.currentTimeMillis() in the place that you want to know the time.
you should call currentTimeMillis minus the start time, where you want to find the total time ran.

Working with time displayed as strings

Alright so I'm taking an AP Computer Science course and up until now I've found the content easy and unchallenging because I already had a background in Java. However now I have run into an issue with some of the code that the course is providing me with and writing a function based off of it. I've googled it, and tested many different things to try and get it to work and to no avail. So hopefully you guys can shed some light on this and perhaps help me figure it out.
First the book provides me with this code as a basic Time class:
public class Time extends Object {
private int itsHour;
private int itsMin;
/** Create an object for the given hour and minute. If min
* is negative, adjust the values to make 0 <= min < 60. */
public Time (int hour, int min) { // constructor
super();
itsHour = hour;
for (itsMin = min; itsMin < 0; itsMin = itsMin + 60) {
itsHour--;
}
} //=======================
/** Return the time expressed in military time. */
public String toString() {
if (itsHour < 10) {
return ("0" + itsHour) + itsMin;
} else {
return ("" + itsHour) + itsMin;
}
}
/** Return the result of adding this Time to that Time. */
public Time add (Time that) {
// Read below at issue #2
}
}
That was the main class they gave us to work with and then they gave a class called TimeTester which is to be used to execute the commands. The comments dictate what should happen.
import javax.swing.JOptionPane;
class TimeTester {
public static void main (String[] args) {
Time t1 = new Time (13, 25);
Time t2 = new Time (8, -150);
JOptionPane.showMessageDialog (null, "1 " + t1.toString());
JOptionPane.showMessageDialog (null, "2 " + t2.toString());
Time t3 = t1.add (t2);
JOptionPane.showMessageDialog (null, "3 " + t3.toString());
t1 = t2.add (t3);
JOptionPane.showMessageDialog (null, "1 " + t1.toString());
System.exit (0);
} //=======================
}
Now like I said this code was literally handed to me it's making sense of the code and getting it to work for me that I just literally cannot do. So below are basically the key issues I'm running into.
1) I understand how its supposed to run and what the executors do, but I do not understand what exactly its doing to achieve the results.
2) The add function in the first set of code which was basically it's main class is the main part of the assignment. The assignment reads as follows:
Exercise 4.15 (harder) Write the Time method public Time add (Time
that): The executor returns a new Time object that is the sum of the
two, e.g., 0740 add 1430 is
2210. If the sum is more than 2359, drop the extra 24 hours, e.g., 1300 add 1400 is 300.
Assigned from: http://www.cs.ccsu.edu/~jones/chap04.pdf
When I carry over the values to the add function in the TimeTester executing "now.add(wait)" I go to pull that result using "that" but the values don't pull forward.
I've also tried to change up the functions to perhaps get my own understanding and make it work for me. I changed the Time later call in the TimeTester, and then edited the function add to accept 2 values. Then added this code to the add function:
public Time add (Time time1, Time time2) {
String t1String = time1.toString(); // Value is: "0730"
String t2String = time2.toString(); // Value is: "0245"
int t1convert = Integer.parseInt(t1String, 2); // Value is 730
int t2convert = Integer.parseInt(t2String, 2); // Value is: 245
int total = t1convert + t2convert; // Value added together is: 1015
return total; // Return value of total
}
So my call looked like this:
public static void main (String[] args) {
now = new Time (7, 30); // 7:30 in the morning
wait = new Time (2, 45); // 2 hours 45 minutes
later = now.add (now, wait); // produces 10:15 in the morning
JOptionPane.showMessageDialog(null, now + " + " + wait + " = " + later.toString());
System.exit (0);
}
However all that code would not compile and produce a result which could be returned to my TimeTester, it always produced a compile error of "incompatible types" referring to my return total; line. So it obviously cannot return Integers. So I am just absolutely stuck on what to do to make it add the two times.
3) I cannot use the built in Java time functions where it's formatted with semicolons. I know how to do that part which is why this different way is driving me up the wall.
4) I don't want you to write my code for me, I'd like to gain a better understanding of it and perhaps have my mistakes pointed out so that I can comprehend what in the world is going on with it.
I know it's a long post, but when I ask for help I like to be descriptive and provide everything I can because I know it's going to help me better in the long run and hopefully help the person who helps me track down an answer fast.
(PS. All of this is compiled and ran in a program called BlueJ. It's an online course so I have no instructor in class to ask about it all we have is a monitor.)
Consider a method to add two Time instances (a and b) and return a new Time instance; such a method would look like the inverse of the provided Time constructor loop, for (itsMin = min; itsMin < 0; itsMin = itsMin + 60), specifically - it should increment some hours count (perhaps by adding the hours from a and b) while the number of minutes is > 59 and subtracting 60 minutes at a time... This method might look something like this
public static Time add(Time a, Time b) { // Add two Time(s) together.
if (a == null) { // if a is null, just return b.
return b;
} else if (b == null) { // if b is null, just return a.
return a;
}
int hours = a.itsHour + b.itsHour; // Add the hours together.
int minutes = a.itsMin + b.itsMin; // Add the minutes together.
for (; minutes > 59; minutes -= 60) { // Increment hours as necessary, while
// decrementing the minute count by 60.
hours++;
}
return new Time(hours, minutes); // Return the new Time instance.
}
public static void main(String[] args) {
Time now = new Time(7, 30); // 7:30 in the morning
Time wait = new Time(2, 45); // 2 hours 45 minutes
Time later = Time.add(now, wait); // produces 10:15 in
// the morning
System.out.println(later);
}
Outputs
1015
The compiler is complaining that you are returning an int, when you defined the function return type to be "Time":
public Time add (Time time1, Time time2) {
String t1String = time1.toString(); // Value is: "0730"
String t2String = time2.toString(); // Value is: "0245"
int t1convert = Integer.parseInt(t1String, 2); // Value is 730
int t2convert = Integer.parseInt(t2String, 2); // Value is: 245
int total = t1convert + t2convert; // Value added together is: 1015
return total; // Return value of total
}
The return type is Time:
public Time add (Time time1, Time time2) ...
You return "total", which is of type "int":
int total = t1convert + t2convert;
return total; …
What you would need to do is to make a new Time object which has the answer stored inside of it. For example:
Time t3 = new Time(0, total); // This is assuming that "total" represents the minutes
Regarding the issue in the comment,
#Mike'Pomax'Kamermans Looking at your comment i managed to write this
line of code to see if i could execute it that way and I cannot. "Time
t1 = new Time(this.hour, that.hour); " spits out "cannot find symbol -
variable hour". Any insight into this? – user1686765 3 mins ago
"this.hour" is looking at the current Time instance, which is a instance of the Time class, for a member variable called "hour." If you go to your Time class, you will see that it only has some methods and 2 variables called "itsHour" and "itsMin". So it cannot find the variable "hour" because it does not exist. I think you meant to put "this.itsHour" in place of "this.hour".

Calculating math in GPS format

I'm making a Android Application to calculate Math in GPS Format.
Example:
Given
N 48°44.(30x4) E 019°08.[(13x31)+16]
the App calculates it, and result is:
N 48°44.120 E 019°08.419
Is it possible to do this?
I searched for plugins and solutions, but it's all just for math strings like as "14 + 6".
I am assuming you are working in Java as it is tagged in your question.
You could create a new public class for your GPS coordinates, and store the actual value of the coordinate in the lowest division, which according to your example appears to be minutes or seconds. This allows you to store the value as an int or a double with whatever precision you wish. You could then create a set of private and public methods to complete your mathematical operations and others to display your values in the appropriate fashion:
public class GPSCoordinate {
private double verticalcoord;
private double horizontalcoord;
//Constructors
GPSCoordinate(){
setVertical(0);
setHorizontal(0);
}
GPSCoordinate(double vert, double horiz){
setVertical(vert);
setHorizontal(horiz);
}
//Display methods
public String verticalString(){
return ((int)verticalcoord / 60) + "°" + (verticalcoord - ((int)verticalcoord / 60) *60);
}
public String horizontalString(){
return ((int)horizontalcoord / 60) + "°" + (horizontalcoord - ((int)horizontalcoord / 60) *60);
}
//Setting Methods
public void setVertical(double x){
this.verticalcoord = x;
}
public void setHorizontal(double x){
this.horizontalcoord = x;
}
//Math Methods
public void addMinutesVertical(double x){
this.verticalcoord += x;
}
}
This will allow you to initiate an instance in your main code with a given GPS coordinate, and then you can call your math functions on it.
GPSCoordinate coord1 = new GPSCoordinate(567.23, 245);
coord1.addMinutesVertical(50);
coord1.otherMathFunction(50 * 30);
You will, of course, need to refine the above to make it fit your project. If this isn't helpful, please provide more specifics and I'll see if I can think of anything else that might fit what your looking for.
Can't you just substring the whole thing and search for the expression in the brackets? Then it's just a matter of simple calculation. If I understood the question correctly. The gps data doesn't look like an ordinary expression, so you can't appy math() directly.

Categories

Resources