How to write a function for this simple purpose?

2 views (last 30 days)
I have a variable A. If it is between 5 and 50, B = 10, etc. (like the below). How do I write a function so that B = f(A)? Thanks!
What I listed below are just some examples, and in reality, my A and B could be infinitiely small or infinitely big. For example, I could have an A value between 5x10^-19 and 5x01^-18, in that case B should be equal to 1x10^-18.
%A B
......
0.005-0.05: 0.01
0.05-0.5: 0.1
0.5-5: 1
5-50: 10
50-500: 100
500-5000: 1000
......

Accepted Answer

Image Analyst
Image Analyst on 26 Oct 2019
Try this
b = f(.9) % For example;
b = f(22) % For example;
b = f(333) % For example;
b = f(444) % For example;
function B = f(A)
%A B
lookupTable = [
0.005,0.05, 0.01
0.05,0.5, 0.1
0.5,5, 1
5,50, 10
50,500, 100
500,5000, 1000];
row = A > lookupTable(:, 1) & A <= lookupTable(:, 2);
B = lookupTable(row, 3);
end
  3 Comments
Image Analyst
Image Analyst on 26 Oct 2019
Edited: Image Analyst on 26 Oct 2019
Just modify your lookup table. Or do you just want to take the log10 of the value? Like
B = log10(A/5);
Leon
Leon on 26 Oct 2019
Edited: Leon on 26 Oct 2019
I like this direction! I think the below will do the trick:
B = 10^ floor( log10(A/5)+1 )

Sign in to comment.

More Answers (2)

John D'Errico
John D'Errico on 26 Oct 2019
Edited: John D'Errico on 26 Oct 2019
Here are other approaches that are nicely vectorized, but do not require you to set explicit tests for each bin. For example, suppose you had literally dozens of bins? You don't want to hard code those tests. So instead, you need to learn and use the tools in MATLAB that will allow you to solve the problem in a fully general way.
I've done it here in a way that assumes Z can be any positive value. Where A is below 0.005, it will return 0.001. Where A is greater than 5000, it will return 10000. I was fairly arbitrary in those choices, but it is important that you consider what will happen if the sky actually is falling, and you take care of those degenerate cases. (Good software can be described as a worrywort: ie., always worrying about what will I do if event X happens? How about Y? And, god forbid, what about Z? The best software lets the user down softly whenever possible, and when not, it should provide a clear error explanation to help the user to identify and fix any problems.)
I suppose I could have chosen to make the end conditions return 0 and inf as an alternative.
function B = f(A)
bins = [0 0.005 .05 .5 5 50 500 5000 inf];
vals = [0.001 .01 .1 1 10 100 1000 10000];
ind = discretize(A,bins);
B = vals(ind);
end
Now let me try it:
f([.000001 .002 .2 .6 12 100 1e12 inf])
ans =
0.001 0.001 0.1 1 10 100 10000 10000
So it works as designed. As I said, the nice thing is it allows you to define the function without needing any specific tests. I could have written the tool so that you actually pass in the bin boundaries and values as arguments too, I suppose. That would be more general yet.
Now, could I have written this for the very specific case here, without using discretize? Actually, yes, because you have chosen very simple bin boundaries. In fact, I can do it in one line of code, just using a function handle..
f = @(A) 10.^floor(log10(A*2));
This line of code will work, but note that it has no effective boundaries on the positive real line, as long as you do not exceed the reasonable limits imposed on you by use of double precision arithmetic.
f([.0000000000009, 6, 130000])
ans =
1e-12 10 1e+05
That may or may not be what you want. But it is trivial to fix if you did want limits. For example:
f = @(A) 10.^max(-3,min(4,floor(log10(A*2))));
Again, it works with no problem. Here the lower limit is arbitrarily 0.001, and the upper limit is 10000.
f([.0000000000009, 6, 130000])
ans =
0.001 10 10000

David Hill
David Hill on 26 Oct 2019
function c = f(c)
c(c>=.005&c<.05)=.01;
c(c>=.05&c<.5)=.1;
c(c>=.5&c<5)=1;
c(c>=5&c<50)=10;
c(c>=50&c<500)=100;
c(c>=500&c<=5000)=1000;
end
  3 Comments
David Hill
David Hill on 26 Oct 2019
function c = f(c)
for i=1:length(c)
a=-10;%whatever is maximum expected (10^10)
while round(c(i),a)==0
a=a+1;
end
c(i)=round(c(i),a);
x=num2str(c(i));
x=str2double(regexp(x,'[1-9]','match','once'));
c(i)=c(i)/x;
end
Leon
Leon on 26 Oct 2019
Thank you for another approach of doing this!

Sign in to comment.

Categories

Find more on Characters and Strings in Help Center and File Exchange

Tags

Products


Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!