How can I make the program count the number of decimals of an inputted amount

11 views (last 30 days)
I have this code:
withdrawAmount = input ('Enter amount to Withdraw ');
.
.
.
.
.
Is there anyway the program could count the number of decimals entered for "withdrawAmount"
because i want to be able to use an if statement, saying if the entered amount has more than 2 decimal places, disp('invalid')

Accepted Answer

Walter Roberson
Walter Roberson on 10 Dec 2021
withdrawAmount = input ('Enter amount to Withdraw ');
Is there anyway the program could count the number of decimals entered for "withdrawAmount"
Have a look at this:
withdrawAmount = 0.10
withdrawAmount = 0.1000
S = sprintf('%.99g', withdrawAmount)
S = '0.1000000000000000055511151231257827021181583404541015625'
length(S)
ans = 57
So the number of decimals entered was (57 - length('0.')) --> 55
Can you prove otherwise? NO. The user might have chosen to enter that long string of digits, and the binary value stored in withdrawAmount would be exactly the same.
Furthermore, you used input() . The user might have chosen to respond with (for example)
1/3
Now how many digits did they enter?
Remember that input() with no 's' option executes whatever the user entered as a command . And if the results are floating point, then they are stored in IEEE 754 double precision binary, which does not store values in base 10. You are completely unable to tell whether the user entered 0.1 or 0.10 or 0.10000 or 1/10 when you use input() without the 's' option.
Moral of the story: If you use input() and you need to validate something about the form that the user entered the number, then you need to use the 's' option.
  23 Comments
Walter Roberson
Walter Roberson on 13 Dec 2021
Edited: Walter Roberson on 13 Dec 2021
function posnum = getPositiveNumber()
prompts = {'please enter a numeric amount : ',
'please enter a positive value : ',
'please limit your amount to 2 decimal places : '};
prompt_num = 1;
while true
prompt = prompts{prompt_num};
p = strtrim(input(prompt, 's'));
if ~isempty(regexp(p, '\.[0-9]{3,}'))
prompt_num = 3;
continue;
end
if ~isempty(regexp(p, '^-'))
prompt_num = 2;
continue;
end
vetted = regexp(p, '^([0-9]+(\.[0-9]{0,2})?$)|^\.[0-9]{1,2}$', 'match');
if isempty(vetted)
prompt_num = 1;
continue;
end
trial_num = str2double(vetted);
if isnan(trial_num)
fprintf('Bug validating number. Please report input |%s|\n', p);
prompt_num = 1;
continue;
end
break;
end
posnum = trial_num;
end

Sign in to comment.

More Answers (2)

Image Analyst
Image Analyst on 9 Dec 2021
Try this:
numberOfDecimalPlaces = inf;
while numberOfDecimalPlaces >= 3
withdrawAmountString = input ('Enter amount to Withdraw : ', 's');
dotLocation = find(withdrawAmountString == '.', 1, 'last');
numberOfDecimalPlaces = length(withdrawAmountString) - dotLocation;
if numberOfDecimalPlaces >= 3
warningMessage = sprintf('You entered %d numbers to the right of the decimal point.\nPlease use 2 or less.', numberOfDecimalPlaces)
uiwait(warndlg(warningMessage));
else
% Good! It's 2 or less. Now convert string to a number.
withdrawAmount = str2double(withdrawAmountString);
end
end
  7 Comments
Image Analyst
Image Analyst on 10 Dec 2021
Sure. You can detect if there is some non-number there like this:
allDigits = all((withdrawAmountString >= '0' & withdrawAmountString <= '9') | withdrawAmountString == '.')
if ~allDigits
% Tell user they messed up.
% Then set numberOfDecimalPlaces = 3 to force it to try again.
numberOfDecimalPlaces = 3; % Ensure it will ask again.
end
Alternatively you can extract only the digits.
mask = (withdrawAmountString >= '0' & withdrawAmountString <= '9') | withdrawAmountString == '.'
withdrawAmountString(~mask) = []; % Remove non-numbers.
Tariq Hammoudeh
Tariq Hammoudeh on 11 Dec 2021
Edited: Tariq Hammoudeh on 11 Dec 2021
The problem with this is that it interferes with another piece of code, my code is:
transactionType= input('1:withdraw 2:deposit 3:account balance 4:end use 5:end program');
switch transactionType
%if withdraw chosen
case 1
decimalPlaces = inf; % variable for the number of decimal places in the entered withdrawal amount
%this lets the user enter a different amount if they enter an amount with more than 2 decimal places
while decimalPlaces >= 3
withdrawAmountString = input ('Enter amount to Withdraw : ', 's'); %inputed withdrawal amount
decimalLocation = find(withdrawAmountString == '.', 1, 'last');
decimalPlaces = length(withdrawAmountString) - decimalLocation;
if decimalPlaces >= 3
disp("Please limit your amount to 2 numbers to the right of the decimal point.");
else
% if enetered amount has 2 or less decimal places, convert string
% to a number and contunue.
withdrawAmount = str2double(withdrawAmountString);
end
end
noLetters = all((withdrawAmountString >= '0' & withdrawAmountString <= '9') | withdrawAmountString == '.');
if ~noLetters
withdrawAmount=input (' please enter a numeric value')
numberOfDecimalPlaces = 3;
end
%this lets the user enter a different amount if they enter a negative number
while withdrawAmount <= 0
withdrawAmount= input('invalid amount, please enter a positive number');
end
the thing with it now is that after i enter a number a number < 0 it also tells me to enter a numeric value, so how can i do it so that it only tells me this after entering a number and not when i enter a negative number
Please note: I changed it to
withdrawAmount= input(please enter numeric data) because when i would enter a letter it takes me back to switch case options instead of letting me directly enter a new number

Sign in to comment.


David Hill
David Hill on 9 Dec 2021
if you don't care about zeros entered.
x=46.4500000;%if this would be valid
if ~isequal(floor(x*100),x*100)
'invalid'
end
  1 Comment
Stephen23
Stephen23 on 10 Dec 2021
Sadly this approach fails for many values that could be legitmately described as having only two decimal digits in the fraction part, for example:
x = 0:0.01:10;
y = find(floor(100*x)~=100*x)
y = 1×150
8 15 29 30 56 57 58 59 110 111 112 113 114 115 116 117 202 204 206 208 219 221 223 225 227 229 231 233 244 246
x(y)
ans = 1×150
0.0700 0.1400 0.2800 0.2900 0.5500 0.5600 0.5700 0.5800 1.0900 1.1000 1.1100 1.1200 1.1300 1.1400 1.1500 1.1600 2.0100 2.0300 2.0500 2.0700 2.1800 2.2000 2.2200 2.2400 2.2600 2.2800 2.3000 2.3200 2.4300 2.4500

Sign in to comment.

Tags

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!