## How to write a function for this simple purpose?

Leon

### Leon (view profile)

님이 질문을 제출함. 26 Oct 2019
최근 활동 Leon

### Leon (view profile)

님이 댓글을 추가함. 26 Oct 2019
Image Analyst

### Image Analyst (view profile)

님이 답변을 채택함.
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
......

로그인 to comment.

R2019b

## 답변 수: 3

Image Analyst

### Image Analyst (view profile)

님의 답변 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

Leon

### Leon (view profile)

26 Oct 2019
Many thanks. This works. The only thing is that what I listed 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. Sorry for not making that clear from the start.
Image Analyst

### Image Analyst (view profile)

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 (view profile)

26 Oct 2019
I like this direction! I think the below will do the trick:
B = 10^ floor( log10(A/5)+1 )

로그인 to comment.

John D'Errico

### John D'Errico (view profile)

님의 답변 26 Oct 2019
John D'Errico

### John D'Errico (view profile)

님이 편집함. 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

26 Oct 2019
Very nice!
Leon

### Leon (view profile)

26 Oct 2019
Beautiful!
Thank you so much.

로그인 to comment.

David Hill

### David Hill (view profile)

님의 답변 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

Leon

### Leon (view profile)

26 Oct 2019
Many thanks for the solution! Please see above for my comments. My apologies for not making it super clear.
David Hill

### David Hill (view profile)

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 (view profile)

26 Oct 2019
Thank you for another approach of doing this!

로그인 to comment.