Is there a way to implement the math function Log() into an equation with an iphone app? im working on right now that without the log function requires about 400 + if and else if statements. I have already wrote out these if and else if statements. half of them work and the other half keeps returning 0.00 . after HOURS of trying to find the problem and compare it to the part that does work i can still not figure it out. i know i can do simple math (add, subtract, divide, mulitply, etc), but i havnt found anything searching forums, google, etc that tells me how to add a Log function. if i could do this i can cut my code down from like 500 lines to about 40 tops. can anyone help me with this or at least point me in the right direction as to where i can find a thread or tutorial on this?
I already fixed Shaun's example code posted in his answer, but just to be perfectly clear, there were two issues at work:
First, he wasn't including <math.h> and using log from the system math library.
Second, he omitted the multiplication operator in the expression .19077f(logf(abNeckFactor)); we often write mathematics this way, but it is not syntactically valid C (or Obj-C) code.
Shaun, I would advise you to spend some more time reading up on what's available in C and Objective-C; an enormous amount of functionality is present in the language, and a few hours spent learning about what's already done for you will spend you many, many hours of searching for things in the future.
Note also that the log function is the base-e logarithm. Many people in technical fields outside of mathematics and computing use log to refer instead to the base-10 logarithm; if that's what you need, you will want to call log10( ) -- or log10f( ) -- instead.
#import <math.h>
// ...
double someLog = log(someDouble);
(Note: I used double/log here, but you might consider using float/logf if speed is an issue as they could be faster on the iPhone (IIRC).)
I know you've already got the answer to your question, but here's way of not having to write tons of if, else if, else if, .... else, for future reference.
Store the answers in an array.
For instance you could define an array of arrays that looks like this:
[(min, max, value),(min, max, value),...]. Then loop through the array.
arr = {{min, max, value}, {min, max, value}, ...}
for i in range(0, arr.length)
if(arr[i][min_i] < x && x < arr[i][max_i]) {return arr[val_i]}
There is probably a way figuring how to map the x to a index of an array like x/(max-min) so that log(x) would be arr[x/(max-min)]. But my point is, it is alot cleaner to have an array or dictionary and search through it than having a bunch of if, else if, else if, ... statements.
Related
I noticed a HashSet<int> performing very slowly when working on a Flutter project. I had about 20,000 integers in a Set, and checking set.contains() took a very long time. But when I use toString() to convert all items to string, it performed 1000x faster.
I then tried to create a minimal reproducible code with 10 million random integers, but I couldn't reproduce the issue. Turns out, something special about these data caused the extreme slowness. I've attached a test code (and data) at the end of this question.
How to reproduce:
First, click "add int" button to add 14790 integers to a set. Then click "query int" (runs set.contains(123)) and "query string" (runs set.contains('123')). Observe that: 1. both operations are super slow; 2. the int version is slower than the string version. Picture:
Then click "clear items", then "add string" to add the toString() version of the data. Then click "query int" and "query string" again, notice how much faster it becomes. Picture:
Lastly, click both "add int" and "add string" to create a mixed set (with twice the entries). Observe that the querying times dropped in half for the int version, as if the faster strings helped "dilute" the problem. Picture:
I've had several friends running the same test code on various machines (intel i5, apple M1, snapdragon), timings are different but the conclusions are the same.
What's not the answer here:
Here are some things I considered, but they couldn't explain what's happening with some more tests.
Maybe int needs boxing, whereas string is already an object?
That's probably not the issue here. With 1 million randomly generated values, ints performed faster than strings.
string is immutable so their hash value could be cached?
I don't know if they are cached, but this doesn't explain the results observed with 1 million randomly generated values.
int hash resulted in a lot of collisions?
I tried to print out .hashCode for all ints and strings in the data set, and verified they are all unique.
Test code:
The full test code with data is too long for StackOverflow, I've put it here https://pastebin.com/raw/4fm2hKQB instead.
So yeah, I'm lost, if anyone could help me understand what's going on that'll be greatly appreciated!
I commented on the issue in the Dart repo. For completeness I will mention the 'answer' part of the comment here.
The implementations of HashSet and LinkedHashSet make the assumption that the key.hashCode values are 'good' hash codes that are reasonably distributed over a range of integers so that the lower N bits do not collide or nearly collide to 'bunch up' in the hash-table. Unfortunately int.hashCode does not have this property as it is effectively the identity function.
Things go wrong when the lower bits of all the keys are the same (or have only a few of the possible values) so taking the lower N bits gives the same effective hash code value. This is just the power-of-two version of the % 1000 example mentioned by #ch271828n.
#ch271828n mentions using a different hashCode. This is probably the best short-term solution. Use LinkedHashSet(hashCode: dispersedHashCode) with something like this:
int dispersedHashCode(e) { // untested!
int hash = e.hashCode;
// Odd number with 30%-50% of the bits set in an irregular pattern.
hash *= 0x1736B4D29;
hash += hash >>> 20;
// maybe do it again to let bits higher that 20 influence the low bits.
return hash;
}
Something like this would ideally be built into the core library hashed structures. This might take a long time since, realistically, a performance issue with a simple work-around will be likely be prioritized behind security bugs, incorrect behaviour bugs, performance issues with no work-around, and new features that enable customers to do things that are otherwise impossible to difficult to do.
A completely different approach would be to use an ordered Set like SplayTreeSet.
I am also considering hash collision problem.
int hash resulted in a lot of collisions?
I tried to print out .hashCode for all ints and strings in the data set, and verified they are all unique.
Well, "all unique" does not mean "there is no collision". For a hash set, the number of bins are much less than the number of hashcode. For example, suppose you have a hash set with 1000 bins, and the mapping from hashCode to bin index is a simple bin index := hashCode % 1000, and suppose your data has hashCode like 0, 1000, 2000, 3000 etc. In this artificial case, your data has all unique hashCode, but they all fall into the first bin out of the 1000 bins. Huge collision!
A simple approach to debug whether it is the problem of hashcode: Re-run the program with LinkedHashSet(hashCode: (e) => some_other_hash_approach(e), equals: ...). By using such a new hash set, you can test on other hashCode generating functions. If some hashCode generating functions do not result in the same extremely slow speed, it is highly because of the original hashCode function which causes collision.
In addition, you can even use the same hashCode method for both the int and the String case. Then you guarantee that both cases have exactly the same collision behavior. Then it is easy to see whether collision is the cause, or is unrelated.
Another debug approach: Look at the C++ source code of LinkedHashSet, and see what algorithms it uses to assign data to bins. Then check whether collision as mentioned above happens or not.
A third debug method: Compile the pure-Dart program into an executable, and use profilers like perf to run it. Then you can see which code is hottest and consume most of the time. You may need debug symbols of Dart's native C++ code, which should be fetchable.
I saw this article:
https://itnext.io/comparing-darts-loops-which-is-the-fastest-731a03ad42a2
It says that ".map" is slow with benchmark result
But I don't understand why slower than while/for loop
How does it work in low level?
I think it's because .map is called an unnamed method like this (_){ }
Can you explain that in detail?
Its because mapping an array will create a copy of each value than modify the original array.
Since a while/for loop does not copy the values but rather just accesses them using their index, it is a lot faster.
Can you explain that in detail?
It's like saying "I don't understand why hitchhiking on the back of a construction truck is so much slower than taking the high speed train to my destination".
The only detail that is important is that map is not a loop. map() internally probably uses a loop of some kind.
This person is misusing a method call that is meant for something else, just because a side-effect of that call when combining it with a call materializing the iterable, like toList(), is that it loops through the iterable given. It doesn't even have the side effect on it's own.
Stop reading "tutorials" or "tips" of people misusing language features. map() is not a loop. If you need a loop, use a loop. The same goes for the ternary operator. It's not an if, if you need an if, use it.
Use language features for what they are meant, stop misusing language features because their side-effect does what you want and then wondering why they don't work as well as the feature actually meant for it.
Sorry if this seems a bit ranty, but I have seen countless examples by now. I don't know where it comes from. My personal guess is "internet tutorials". Because everybody can write one. Please don't read them. Read a good book. It was written by professionals, proofread, edited, and checked. Internet tutorials are free, written by random people and about worth as much as they cost.
I created a test page where I'm using hyperHTML to showcase 10,000 buttons. The code is a little large to post onto stackoverflow, but you can view source on this page here to see the code (expect delay after clicking).
hyperHTML is taking more time than expected to complete its work, which makes me think I'm misusing it.
Any suggested optimizations?
Update: It seems I was using an older version of hyperHTML. The current version is blazing fast on this test.
Update beside the test being not a real world use case, there was room for improvements on linearly holed template literals so that 7 seconds now are down to roughly 70 ms ... however, the rest applies, that is not how you use hyperHTML.
I created a test page where I'm using hyperHTML to showcase 10,000 buttons
You are not using hyperHTML properly at all. It's a declarative library that wants you to forget the usage of document.createElement or addEventListener or even setAttribute.
It looks like you are really trying hard to avoid all its utility with this example, and since this is not your first question about hyperHTML, it looks like you are avoiding its documentation and examples on purpose.
In such case, what are you trying to achieve?
The code is a little large to post onto stackoverflow
That code is an absolute nonsense, IMO. No sane person would ever write 10000 buttons inline like you did there, and I bet that was machine generated indeed.
The code to create 10K buttons, or one of the ways, in hyperHTML, fits very easily in this forum:
function createButton(content) {
return wire(document, ':' + content)`
<button onclick=${onclick}>${content}</button>`;
}
function onclick(e) {
alert(`You clicked a button labeled: ${e.target.textContent}.`);
}
const buttons = [];
for (let i = 0; i < 10000; i++)
buttons.push(createButton('btn-' + i));
bind(document.body)`${buttons}`;
That's it. You can eventually optimize the container that will render such content, and to preserve your original demo, you can also add some text content which has very doubtful meaning but, in this very specific case, would need just a craeteTextNode, something again not really needed but the only thing that makes sense for a benchmark, so that the result is the one shown in this Code Pen, and the execution time here is 19.152ms, meaning you can show 10.000 buttons at 50FPS.
However, showing 10.000 buttons all at once has close to 0 use cases in the real-world, so you should rather understand what is hyperHTML, what it solves, and how to benefit from it, instead of using it as an innerHTML.
hyperHTML is 100% different from innerHTML, the sooner you understand this, the better it is.
If you need innerHTML, don't use hyperHTML.
If you want to use hyperHTML, forget any DOM operation that is not declarative, unless really needed, where this wasn't the case at all.
I was asked question about what would happen if I try to retrieve a reference value and then try to change it within the same line of code. My answer was that nothing will happen because as I tried to do this before I did not encounter any compiler errors (at least in C# or Java).
What is the real answer to this?
This is example with the pseudo code:
Module main()
Call changeNumber(10)
End Module
Module changeNumber(Integer Ref number)
Set number = number * number
Display number
End Module
(PS. Sorry for not formatting/creting this post correctly. I'm having bit of an issue here.)
There would be no unusual side effects, if that's what you're asking. The language specifications dictate a specific order of execution (number * number is evaluated, then set to number), which prevents any issues from occurring.
Nothing would happen, in your particular pseudo code.
In reference to a question you asked after this question -
Actually there could be issues in some rare instance, but it would depend on how you are allocating space for the number and your coding language. Consider this. you are explicitly naming the data type as an int, well what if the accepted input is a larger number than an int can handle (or a negative number), that ends up being x integers long and then you multiply it by that same number, your allocated space (which usually has padding with integer) could also have insufficient space that is too small for this particular instance, which would cause a segmentation fault in C. depending on which language you're using, whether it's higher level than C, it may have compilation checks for this case, but not always.
I've recently learned Haskell, and am trying to carry the pure functional style over to my other code when possible. An important aspect of this is treating all variables as immutable, i.e. constants. In order to do so, many computations that would be implemented using loops in an imperative style have to be performed using recursion, which typically incurs a memory penalty due to the allocation a new stack frame for each function call. In the special case of a tail call (where the return value of a called function is immediately returned to the callee's caller), however, this penalty can be bypassed by a process called tail call optimization (in one method, this can be done by essentially replacing a call with a jmp after setting up the stack properly). Does MATLAB perform TCO by default, or is there a way to tell it to?
If I define a simple tail-recursive function:
function tailtest(n)
if n==0; feature memstats; return; end
tailtest(n-1);
end
and call it so that it will recurse quite deeply:
set(0,'RecursionLimit',10000);
tailtest(1000);
then it doesn't look as if stack frames are eating a lot of memory. However, if I make it recurse much deeper:
set(0,'RecursionLimit',10000);
tailtest(5000);
then (on my machine, today) MATLAB simply crashes: the process unceremoniously dies.
I don't think this is consistent with MATLAB doing any TCO; the case where a function tail-calls itself, only in one place, with no local variables other than a single argument, is just about as simple as anyone could hope for.
So: No, it appears that MATLAB does not do TCO at all, at least by default. I haven't (so far) looked for options that might enable it. I'd be surprised if there were any.
In cases where we don't blow out the stack, how much does recursion cost? See my comment to Bill Cheatham's answer: it looks like the time overhead is nontrivial but not insane.
... Except that Bill Cheatham deleted his answer after I left that comment. OK. So, I took a simple iterative implementation of the Fibonacci function and a simple tail-recursive one, doing essentially the same computation in both, and timed them both on fib(60). The recursive implementation took about 2.5 times longer to run than the iterative one. Of course the relative overhead will be smaller for functions that do more work than one addition and one subtraction per iteration.
(I also agree with delnan's sentiment: highly-recursive code of the sort that feels natural in Haskell is typically likely to be unidiomatic in MATLAB.)
There is a simple way to check this. Create this function tail_recursion_check:
function r = tail_recursion_check(n)
if n > 1
r = tail_recursion_check(n - 1);
else
error('error');
end
end
and run tail_recursion_check(10), for example. You are going to see a very long stack trace with 10 items that says error at line 3. If there were tail call optimization, you would only see one.