How to write a function for this simple purpose?

2 ビュー (過去 30 日間)
Leon
Leon 2019 年 10 月 26 日
コメント済み: Leon 2019 年 10 月 26 日
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
......

採用された回答

Image Analyst
Image Analyst 2019 年 10 月 26 日
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 件のコメント
Image Analyst
Image Analyst 2019 年 10 月 26 日
編集済み: Image Analyst 2019 年 10 月 26 日
Just modify your lookup table. Or do you just want to take the log10 of the value? Like
B = log10(A/5);
Leon
Leon 2019 年 10 月 26 日
編集済み: Leon 2019 年 10 月 26 日
I like this direction! I think the below will do the trick:
B = 10^ floor( log10(A/5)+1 )

サインインしてコメントする。

その他の回答 (2 件)

John D'Errico
John D'Errico 2019 年 10 月 26 日
編集済み: John D'Errico 2019 年 10 月 26 日
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
  2 件のコメント
David Hill
David Hill 2019 年 10 月 26 日
Very nice!
Leon
Leon 2019 年 10 月 26 日
Beautiful!
Thank you so much.

サインインしてコメントする。


David Hill
David Hill 2019 年 10 月 26 日
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 件のコメント
David Hill
David Hill 2019 年 10 月 26 日
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 2019 年 10 月 26 日
Thank you for another approach of doing this!

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeMATLAB についてさらに検索

タグ

製品


リリース

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by