I am in need of assistance. I will be computing a measured variable, then taking the top 100 values of these and averaging them. Please remember, I have been teaching myself only for the past 6 weeks and what is obvious to some, will not necessarily be obvious to me.
In essence, say 'double x' is the variable, that I have many close values for. What I need is a way to compute the sum (then average) of the top 100 of these values.
In my research, the closest thing I can see that would suit what I need is 'nextAfter(double start, double direction); and before this, using 'max' to determine the maximum value, would this be the correct starting point:
double xm = max(x);
static double (xm, x < xm);
My question is how to get the sum of the top 100 values (the maximum and 99 nextAfter's) - averaging would be easy - just dividing by 100.
To compute the average of the largest n values you read from the source, you need to store at least these values. Since at any given point before the end you don't know whether some of the largest n values overall will come later, you need to keep track the largest n values seen so far.
A simple way to do that is to store the largest values in a heap or priority queue, since that allows easy adding of new values and finding (and removing) of the smallest of the stored values. The default PriorityQueue is well-suited for this task, since it uses the natural ordering of the elements, and thus polling removes the smallest of the stored elements. If one wanted to compute the average of the n smallest elements, one would need to use a PriorityQueue with a custom Comparator (or in this special case, simply negating all values and using the natural ordering would work too).
The lazy way (less code) to achieve the desired is to simply add each incoming value to the queue, and if the queue's size exceeds n [then it must be n+1] remove the smallest element from the queue:
// vp is the value provider
while(vp.hasNext()) {
// read the next value and add it to the queue
pq.add(vp.nextValue());
if (pq.size() > topSize) {
pq.poll();
}
A slightly more involved way is to first check whether the new value needs to be added, and only modify the queue when that is the case,
double newValue = vp.nextValue();
// Check if we have to put the new value in the queue
// that is the case when the queue is not yet full, or the smallest
// stored value is smaller than the new
if (pq.size() < topSize || pq.peek() < newValue) {
// remove the smallest value from the queue only if it is full
if (pq.size() == topSize()) {
pq.poll();
}
pq.add(newValue);
}
This way is potentially more efficient, since adding a value to the queue and removing the smallest are both O(log size) operations, while comparing to the smallest stored value is O(1). So if there are many values smaller than the n largest seen before, the second way saves some work.
If performance is critical, be aware that a PriorityQueue cannot store primitive types like double, so the storing (and retrieving for the average computation) involves boxing (wrapping a double value in a Double object) resp. unboxing (pulling the double value from a Double object), and consequently an indirection from the underlying array of the queue to the actual values. Those costs could be avoided by implementing a heap-based priority queue using a raw double[] yourself. (But that should rarely be necessary, usually, the cost of the boxing and indirections would constitute only a minute part of the overall processing.)
A simple-minded complete working example:
import java.util.PriorityQueue;
/**
* Example class to collect the largest values from a stream and compute their
* average.
*/
public class Average {
// number of values we want to save
private int topSize;
// number of values read so far
private long count = 0;
// priority queue to save the largest topSize values
private PriorityQueue<Double> pq;
// source of read values, could be a file reader, a device reader, or whatever
private ValueProvider vp;
/**
* Construct an <code>Average</code> to sample the largest <code>n</code>
* values from the source.
*
* #param tops Number of values to save for averaging.
* #param v Source of the values to sample.
*
* #throws IllegalArgumentException when the specified number of values is less than one.
*/
public Average(int tops, ValueProvider v) throws IllegalArgumentException {
if (tops < 1) {
throw new IllegalArgumentException("Can't get average of fewer than one values.");
}
topSize = tops;
vp = v;
// Initialise queue to needed capacity; topSize + 1, since we first add
// and then poll. Thus no resizing should ever be necessary.
pq = new PriorityQueue<Double>(topSize+1);
}
/**
* Compute the average of the values stored in the <code>PriorityQueue<Double></code>
*
* #param prio The queue to average.
* #return the average of the values stored in the queue.
*/
public static double average(PriorityQueue<Double> prio) throws IllegalArgumentException {
if (prio == null || prio.size() == 0) {
throw new IllegalArgumentException("Priority queue argument is null or empty.");
}
double sum = 0;
for(Double d : prio) {
sum += d;
}
return sum/prio.size();
}
/**
* Reads values from the provider until exhausted, reporting the average
* of the largest <code>topSize</code> values read so far from time to time
* and when the source is exhausted.
*/
public void collectAverage() {
while(vp.hasNext()) {
// read the next value and add it to the queue
pq.add(vp.nextValue());
++count;
// If the queue was already full, we now have
// topSize + 1 values in it, so we remove the smallest.
// That is, conveniently, what the default PriorityQueue<Double>
// gives us. If we wanted for example the smallest, we'd need
// to use a PriorityQueue with a custom Comparator (or negate
// the values).
if (pq.size() > topSize) {
pq.poll();
}
// Occasionally report the running average of the largest topSize
// values read so far. This may not be desired.
if (count % (topSize*25) == 0 || count < 11) {
System.out.printf("Average of top %d values after collecting %d is %f\n",
pq.size(), count, average(pq));
}
}
// Report final average. Returning the average would be a natural choice too.
System.out.printf("Average of top %d values of %d total is %f\n",
pq.size(), count, average(pq));
}
public static void main(String[] args) {
Average a = new Average(100, new SimpleProvider(123456));
a.collectAverage();
}
}
using the interface
/**
* Interface for a source of <code>double</code>s.
*/
public interface ValueProvider {
/**
* Gets the next value from the source.
*
* #return The next value if there is one.
* #throws RuntimeException if the source is exhausted.
*/
public double nextValue() throws RuntimeException;
/**
* Checks whether the source has more values to deliver.
*
* #return whether there is at least one more value to be obtained from the source.
*/
public boolean hasNext();
}
and implementing class
/**
* Simple provider of a stream of <code>double</code>s.
*/
public class SimpleProvider implements ValueProvider {
// State determining which value to return next.
private long state = 0;
// Last allowed state.
private final long end;
/**
* Construct a provider of <code>e</code> values.
*
* #param e the number of values to yield.
*/
public SimpleProvider(long e) {
end = e > 0 ? e : 0;
}
/**
* Default constructor to provide 10000 values.
*/
public SimpleProvider() {
this(10000);
}
public double nextValue() {
++state;
return Math.log(state)*Math.sin(state) + Math.cos(state/2.0);
}
public boolean hasNext() {
return state < end;
}
}
Related
My tide prediction application uses 8 double arrays for tide height calculations. Literally every tide station in the United States requires these to have 37 elements, EXCEPT Anchorage, Alaska which requires 124 elements.
Here is a declaration example
final int NUM_C = 37; //all stations except anchorage use 37
//final int NUM_C = 124; //anchorage uses 124
double a[] = new double[NUM_C + 1];
Can I efficiently specify the array size at the start up of the app? I can determine which is needed. I don't want to burden the application with inefficiency for 99% + of the users to handle this one case. The difference is only about 3K bytes.
Why don't you instantiate the variable in the constructor? It gives you more freedom to do programatic manipulation.
public class Station {
double a[];
public Station(String location) {
if(location.equals("Anchorage")) {
a = new double[124];
} else {
a = new double[37];
}
}
}
As I understand the instantiation of the object fields in the constructor is the normal case, while the instantiation with the declaration is just an additional feature of Java.
As for the speed it does not make a difference, if you specify the size by a literal value, a constant or a variable. A more interesting question is, if you should use ArrayList instead of an array. See here.
public class Station {
ArrayList<Double> a;
public Station(String location) {
if(location.equals("Anchorage")) {
a = new ArrayList<>(124);
} else {
a = new ArrayList<>(37);
}
}
}
My choice would be ArrayList as it is more flexible. Eight times 124 is not a very large number anyway. No reason to worry about performance for this.
After logging in, it's generating a hash value, but still giving error "Some problem occurred! try again".
PayUmoneySdkInitilizer.PaymentParam.Builder builder =
new PayUmoneySdkInitilizer.PaymentParam.Builder();
builder.setAmount(10.0)
.setTnxId("0nf7" + System.currentTimeMillis())
.setPhone(<My phone>)
.setProductName("product_name")
.setFirstName(<My Name>)
.setEmail(<My email>)
.setsUrl("https://www.payumoney.com/mobileapp/payumoney/success.php")
.setfUrl("https://www.payumoney.com/mobileapp/payumoney/failure.php")
.setUdf1("").setUdf2("").setUdf3("").setUdf4("").setUdf5("")
.setIsDebug(false)
.setKey(<mykey>)
.setMerchantId(<my debug merchant id>);
String tnxId="0nf7" + System.currentTimeMillis();
PayUmoneySdkInitilizer.PaymentParam paymentParam = builder.build();
String hashSequence = "<...>|"+tnxId+"|10.0|product_name|<My name>|<My email>|||||||||||salt";
String serverCalculatedHash= hashCal("SHA-512", hashSequence);
Toast.makeText(getApplicationContext(),
serverCalculatedHash, Toast.LENGTH_SHORT).show();
paymentParam.setMerchantHash(serverCalculatedHash);
// calculateServerSideHashAndInitiatePayment(paymentParam);
PayUmoneySdkInitilizer.startPaymentActivityForResult(TrayActivity.this, paymentParam);
public static String hashCal(String type, String str) {
byte[] hashseq = str.getBytes();
StringBuffer hexString = new StringBuffer();
try {
MessageDigest algorithm = MessageDigest.getInstance(type);
algorithm.reset();
algorithm.update(hashseq);
byte messageDigest[] = algorithm.digest();
for (int i = 0; i<messageDigest.length; i++) {
String hex = Integer.toHexString(0xFF &messageDigest[i]);
if (hex.length() == 1) { hexString.append("0"); }
hexString.append(hex);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} return hexString.toString();
}
You use in the code:
.setTnxId("0nf7" + System.currentTimeMillis())
And then later:
String tnxId="0nf7" + System.currentTimeMillis();
Probably not the only problem, but do you really want to use two different values for these (the time may change between the two calls)? Didn't you want the same tnxId in both cases?
TransactionIdProvider.java:
import java.util.Locale;
public class TransactionIdProvider {
private final static String DEFAULT_PREFIX = "ID";
// Convenient prime number for incrementing the counter
private final static long ID_ADD = 0xF0AD; // "f*ck off and die"
// 64b counter with non-trivial start value
private static long idCounter = 0x0101F00DDEADBEEFL;
/**
* Returns ID consisting of prefix string and 64b counter interleaved
* with 32b per-4s-timestamp.
*
* May produce identical ID (collision) when:
* 1) class is reloaded within 4s
* (to fix: serialize "idCounter" upon shutdown/restart of VM, or
* modify prefix per start of VM)
* 2) more than 2^64 IDs are requested within 4s (no fix, unexpected)
* 3) more than 2^64 IDs are requested after cca. 550 years.
* (no fix, unexpected)
* 4) more than one static instance of TransactionIdProvider is used
* (two or more VMs running the app) (to fix put different prefix in
* every VM/server running this)
*
* Length of returned ID is prefix.length() + 24 alphanumeric symbols.
*/
public static synchronized String getNewId(final String prefix) {
idCounter += ID_ADD; // increment counter
// get 32b timestamp per ~4s (millis/4096) (good for ~550 years)
final int timeStamp = (int)(System.currentTimeMillis()>>12);
final int idPart1 = (int)(idCounter>>32);
final int idPart2 = (int)(idCounter);
return String.format(Locale.US, "%s%08X%08X%08X",
prefix, idPart1, timeStamp, idPart2);
}
public static String getNewId() {
return getNewId(DEFAULT_PREFIX);
}
}
Not sure how much usable is this one, and if the ID may be so long. Feel free to use/modify it any way you wish.
Also I wonder, whether I didn't forget about something important, but can't recall anything.
The security aspect of this one is still quite weak, as within 4s time span the ID will be like simple addition, but at least it's not producing 1, 2, 3... series.
Did found some SDK docs, looks like txnId may be 25 chars long, so you have 1 char for prefix only. Or cut down on timestamp, using %07X in format and masking value with 0x0FFFFFFF, that would make it repeat every ~34 years -> 2 letters for prefix. Or change counter to 32b int, should be still more than enough, unless you expect thousands of transactions per second -> that would remove 8 chars. Or base32/base64 the whole ID to shorten it (depends what alphabet is legal for content)...
Or whatever... already spent enough time with this. Hire a pro.
quick question. I am developing a top-down 2d Platformer game with lots of enemies in the map (at least a hundred spawn at the start of each level). Each enemy uses an AI that searches the map for objects with a specified tag, sorts each object into a list based on their distance, then reacts to the object closest to them.
My code works, but the thing is, if the machine my game is running on is slow, then my game lags. I want to be able to port my game to Android and iOS with low end specs.
In pursuit of putting less strain on the CPU, is there a better way to write my AI?
Here is my code:
void Start () {
FoodTargets = new List<Transform>(); // my list
SelectedTarget = null; // the target the enemy reacts to
myTransform = transform;
AddAllFood ();
}
public void AddAllFood()
{
GameObject[] Foods = GameObject.FindGameObjectsWithTag("Object");
foreach (GameObject enemy in Foods)
AddTarget (enemy.transform);
}
public void AddTarget(Transform enemy)
{
if (enemy.GetComponent<ClassRatingScript>().classrating != 1) { // classrating is an attribute each enemy has that determines their identity (like if they are a plant, a herbivore or a carnivore)
FoodTargets.Add (enemy); // adds the object to the list
}
}
private void SortTargetsByDistance() // this is how I sort according to distance, is this the fastest and most efficient way to do this?
{
FoodTargets.Sort (delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
private void TargetEnemy() // this is called every 4 frames
{
if (SelectedTarget == null) {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
else {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
}
if (optimizer <= 2) { // this is a variable that increments every frame and resets to 0 on the 3rd frame. Only every 3rd frame is the target enemy method is called.
optimizer++;
} else {
TargetEnemy ();
// the rest are attributes that the AI considers when reacting to their target
targetmass = SelectedTarget.GetComponent<MassScript> ().mass;
targetclass = SelectedTarget.GetComponent<ClassRatingScript> ().classrating;
mass = this.GetComponent<MassScript> ().mass;
classrating = this.GetComponent<ClassRatingScript> ().classrating;
distance = Vector3.Distance (transform.position, SelectedTarget.transform.position);
optimizer = 0;
}
Is there a more optimized way of doing this? Your help will be much appreciated. Thanks in advance!
I'm not awfully familiar with C# or Unity but I would look very carefully at what sorting algorithm your sorting method is using. If all you want is the closest Game Object, then sorting isn't necessary.
The fastest sorting algorithms, such as Quicksort, are O(n*log(n)). That is to say that the time it takes to sort a collection of n objects is bounded by some constant multiple of n*log(n). If you just want the k closest objects, where k << n, then you can perform k iterations of the Bubble Sort algorithm. This will have time-complexity O(k*n), which is much better then before.
However, if you only need the single closest object, then just find the closest object without sorting (pseudocode):
float smallestDistance = Inf;
object closestObject = null;
foreach object in objectsWithTag {
float d = distance(object, enemy);
if (d < smallestDistance) {
smallestDistance = d;
closestObject = object;
}
}
This extremely simple algorithm has time complexity O(n).
I am trying to do a snowball calculation for debt - for those who don't know - you make minimum payments on all loans from month to month. Once one is paid off, you take that minimum payment and add it to the next one - so on and so forth. I have each of my debt amounts on do while loops, but my screen turns black and I believe it's on an infinite loop. I have 10 total of these, but here are a few just to show how it's working:
int tempTimeTaken=0;
double newPmt = payment1 + aAmt;
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
tempTimeTaken++;
}
newPmt = newPmt + payment2;
for (int i=0;i<tempTimeTaken;i++)
{
if(amount2>0){
amount2 = (amount2 * rate2) - payment2;
}
}
do{
if (amount2>0){
amount2 = (amount2 * rate2) - newPmt;
tempTimeTaken++;}
}while(amount2>0);
Each of the variables not initialized here are retrieved from a sharedpreference earlier in the activity. Once received, it's parsed in to a double (assuming it's not null).
try
{
amount2 = Double.parseDouble(debtAmount2);
}
catch ( Exception e )
{
amount2 = 0;
}
I've also tried the loops as
while (amount>0){
//do stuff
}
and that didn't work either - same effect.
Any suggestions on how to get this not to loop forever?
all data types are double (except tempTimeTaken is int) - initial values vary - they are input in a different activity and carried to this one via sharedpref with a default of 0
Generally the format of while loop is
while(check condition against loop counter){
//do your things
increment/ decrement loop counter
}
in your loop
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
tempTimeTaken++;
}
you are assigning new value to loop counter amount1 and increment a tempTimeTaken. Print the value of amount1 in this loop check whether it gets negative at some point of time eg.
while(amount1>0){
amount1 = (amount1 * rate1) - newPmt;
Log.d("loop","Value of amount1 :"+amount1);
tempTimeTaken++;
}
I am creating in my app bunch of programmatic Views. As it appeared to be they all by default have the same id=-1. In order to work with them I need to generate unique id's.
I have tried several approaches - random number generation and based on current time, but anyway there's no 100% guarantee that different Views will have different id's
Just wondering is there any more reliable way to generate unique ones? Probably there's special method/class?
Just want to add to Kaj's answer, from API level 17, you can call
View.generateViewId()
then use the View.setId(int) method.
In case you need it for targets lower than level 17, here is its internal implementation in View.java you can use directly in your project:
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
* Generate a value suitable for use in {#link #setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
public static int generateViewId() {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
ID number larger than 0x00FFFFFF is reserved for static views defined in the /res xml files. (Most likely 0x7f****** from the R.java in my projects.)
From the code, somehow Android doesn't want you to use 0 as a view's id, and it needs to be flipped before 0x01000000 to avoid the conflits with static resource IDs.
Just an addition to the answer of #phantomlimb,
while View.generateViewId() require API Level >= 17,
this tool is compatibe with all API.
according to current API Level,
it decide weather using system API or not.
so you can use ViewIdGenerator.generateViewId() and View.generateViewId() in the
same time and don't worry about getting same id
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
/**
* {#link View#generateViewId()}要求API Level >= 17,而本工具类可兼容所有API Level
* <p>
* 自动判断当前API Level,并优先调用{#link View#generateViewId()},即使本工具类与{#link View#generateViewId()}
* 混用,也能保证生成的Id唯一
* <p>
* =============
* <p>
* while {#link View#generateViewId()} require API Level >= 17, this tool is compatibe with all API.
* <p>
* according to current API Level, it decide weather using system API or not.<br>
* so you can use {#link ViewIdGenerator#generateViewId()} and {#link View#generateViewId()} in the
* same time and don't worry about getting same id
*
* #author fantouchx#gmail.com
*/
public class ViewIdGenerator {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
#SuppressLint("NewApi")
public static int generateViewId() {
if (Build.VERSION.SDK_INT < 17) {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
}
Since support library 27.1.0 there's generateViewId() in ViewCompat
ViewCompat.generateViewId()
Create a singleton class, that has an atomic Integer. Bump the integer, and return the value when you need a view id.
The id will be unique during the execution of your process, but wil reset when your process is restarted.
public class ViewId {
private static ViewId INSTANCE = new ViewId();
private AtomicInteger seq;
private ViewId() {
seq = new AtomicInteger(0);
}
public int getUniqueId() {
return seq.incrementAndGet();
}
public static ViewId getInstance() {
return INSTANCE;
}
}
Note that the id might not be unique, if there already are views that have ids in the view 'graph'. You could try to start with a number that is Integer.MAX_VALUE, and decrease it instead of going from 1 -> MAX_VALUE
Regarding the fallback solution for API<17, I see that suggested solutions start generating IDs starting from 0 or 1. The View class has another instance of generator, and also starts counting from number one, which will result in both your and View's generator generating the same IDs, and you will end up having different Views with same IDs in your View hierarchy. Unfortunately there is no a good solution for this but it's a hack that should be well documented:
public class AndroidUtils {
/**
* Unique view id generator, like the one used in {#link View} class for view id generation.
* Since we can't access the generator within the {#link View} class before API 17, we create
* the same generator here. This creates a problem of two generator instances not knowing about
* each other, and we need to take care that one does not generate the id already generated by other one.
*
* We know that all integers higher than 16 777 215 are reserved for aapt-generated identifiers
* (source: {#link View#generateViewId()}, so we make sure to never generate a value that big.
* We also know that generator within the {#link View} class starts at 1.
* We set our generator to start counting at 15 000 000. This gives us enough space
* (15 000 000 - 16 777 215), while making sure that generated IDs are unique, unless View generates
* more than 15M IDs, which should never happen.
*/
private static final AtomicInteger viewIdGenerator = new AtomicInteger(15000000);
/**
* Generate a value suitable for use in {#link View#setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
public static int generateViewId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return generateUniqueViewId();
} else {
return View.generateViewId();
}
}
private static int generateUniqueViewId() {
while (true) {
final int result = viewIdGenerator.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (viewIdGenerator.compareAndSet(result, newValue)) {
return result;
}
}
}
}