You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
How can I make the program count the number of decimals of an inputted amount
3 views (last 30 days)
Show older comments
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
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
S = sprintf('%.99g', withdrawAmount)
length(S)
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
Tariq Hammoudeh
on 10 Dec 2021
Thanks for that, but what i needed is to just let the program give the user another chance to enter a different number if they enter a number with more than 2 decimal places. and i only needed that because i later have a function that counts the least number of cash needed to output the withdrawal amount, and if the amount has more than 2 decimal places it doesnt work correctly.
Walter Roberson
on 10 Dec 2021
withdrawAmountString = input ('Enter amount to Withdraw : ', 's'); %inputed withdrawal amount
vetted = regexp(withdrawAmountString, '^([0-9]+(\.[0-9]{0,2})?$)|^\.[0-9]{1,2}$', 'match');
if isempty(vetted)
user did not enter valid string
else
withdrawAmount = str2double(vetted);
end
You might prefer to use the newer pattern facility if your MATLAB is new enough.
Tariq Hammoudeh
on 10 Dec 2021
is there a way to loop it so that if a number with more than 2 decimal places, it lets me enter again.
Walter Roberson
on 11 Dec 2021
while true
withdrawAmountString = input ('Enter amount to Withdraw : ', 's'); %inputed withdrawal amount
vetted = regexp(withdrawAmountString, '^([0-9]+(\.[0-9]{0,2})?$)|^\.[0-9]{1,2}$', 'match');
if ~isempty(vetted)
withdrawAmount = str2double(vetted);
break
end
end
Tariq Hammoudeh
on 11 Dec 2021
Edited: Tariq Hammoudeh
on 11 Dec 2021
thank you for that but now when i add it to the rest of my code:
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
while true
withdrawAmountString = input ('please enter a numeric value : ', 's'); %inputed withdrawal amount
vetted = regexp(withdrawAmountString, '^([0-9]+(\.[0-9]{0,2})?$)|^\.[0-9]{1,2}$', 'match');
if ~isempty(vetted)
withdrawAmount = str2double(vetted);
break
end
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
%this lets the user enter a different amount, if they enter an amount that is more than the ATM's cash reserve
while withdrawAmount > CR
withdrawAmount = input('insufficient funds in ATM, please enter a different amount');
end
What happens is that, if i start by entering a number < 0 it aslo tells me to "enter a numeric value" instead of "enter a positive value", and also if i start with a number greater than CR i also get "enter a numeric value", and the only way for me to get the correct message for a number greater than CR is only after i either enter a negative number or a letter and the try after that will give me the correct message. so how can i make it give me the correct message for each
Walter Roberson
on 11 Dec 2021
What happens is that, if i start by entering a number < 0 it aslo tells me to "enter a numeric value" instead of "enter a positive value",
You never indicated that negative should be considered. Why bother to consider it separately when you could simply declare that negative is an invalid value and change the first message to 'please enter a positive numeric value' ?
But if you must...
vetted = regexp(withdrawAmountString, '^(-?[0-9]+(\.[0-9]{0,2})?$)|^\-?.[0-9]{1,2}$', 'match');
Note that this requires that the - is directly beside the number. If you want to permit spaces then the code would have to be changed a little. Also, if you want to permit leading or trailing spaces then the code would have to be changed a little.
Walter Roberson
on 11 Dec 2021
while withdrawAmount > CR
withdrawAmount = input('insufficient funds in ATM, please enter a different amount');
end
That code does not validate the input amount.
You should create a function that loops until it gets a validated positive number. Using a function would make your code a lot cleaner.
Tariq Hammoudeh
on 11 Dec 2021
vetted = regexp(withdrawAmountString, '^(-?[0-9]+(\.[0-9]{0,2})?$)|^\-?.[0-9]{1,2}$', 'match');
i tried this but now what happens is that if i enter a negative number i get the correct message, also if i enter a letter i also get the correct message, but then if i enter a letter and get the message "please enter a positive numeric value" then i enter a negative number, here the code continues and takes the negative number as the withdraw amount. So how can i fix that.
Also for your second point:
while withdrawAmount > CR
withdrawAmount = input('insufficient funds in ATM, please enter a different amount');
end
This code works fine and it doesnt let me enter a value more than CR and lets me try again,
Tariq Hammoudeh
on 11 Dec 2021
this code even made it so that even if i enter a valid amount it displays "please enter a positive numeric value"
Walter Roberson
on 11 Dec 2021
Edited: Walter Roberson
on 11 Dec 2021
while true
withdrawAmount = getPositiveNumber();
if withdrawAmount > CR
fprintf('insufficient funds in ATM, please enter a different amount\n');
else
break
end
end
function posnum = getPositiveNumber()
prompt1 = 'please enter a numeric value : ';
prompt2 = 'please enter a positive value : ';
prev_was_negative = false;
while true
if prev_was_negative
prompt = prompt2;
else
prompt = prompt1;
end
p = input(prompt, 's');
vetted = regexp(p, '^(-?[0-9]+(\.[0-9]{0,2})?$)|^-?\.[0-9]{1,2}$', 'match');
if isempty(vetted)
prev_was_negative = false;
% fail to match pattern, do nothing special, loop will repeat
else
trial_num = str2double(vetted);
if trial_num < 0
prev_was_negative = true;
elseif ~isnan(trial_num)
prev_was_negative = false;
break
else
% somehow vetted number converted to nan ??
fprintf('Bug validating number. Please report input |%s|\n', p)
end
end
end
posnum = trial_num;
end
Walter Roberson
on 11 Dec 2021
But again, I do not know why you want to bother processing negative separately when you could just refuse to handle it.
Tariq Hammoudeh
on 11 Dec 2021
Edited: Tariq Hammoudeh
on 11 Dec 2021
if theres a way for the program to refuse to handle it, then thats fine, but what i need it to do is to tell me to enter a postive number if a negative number is entered by the user. it doesnt matter if it is processed with the letters or not
Tariq Hammoudeh
on 11 Dec 2021
I tried the new one but it still tells me " enter a numeric value" even if i enter a valid amount.
This is from the command window:
Enter account number 105
1:withdraw 2:deposit 3:account balance 4:end use 5:end program 1
Enter amount to Withdraw : 10
please enter a numeric value :
also if i enter a negative number the first time it displays "enter a numeric value", it only displays "enter a positive number" after the second time of entering a negative number:
Enter account number 234
1:withdraw 2:deposit 3:account balance 4:end use 5:end program 1
Enter amount to Withdraw : -10
please enter a numeric value : -10
please enter a positive value :
Tariq Hammoudeh
on 11 Dec 2021
Edited: Walter Roberson
on 12 Dec 2021
This is all the code related to withdrawing only:
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
while true
withdrawAmount = getPositiveNumber();
if withdrawAmount > CR
fprintf('insufficient funds in ATM, please enter a different amount\n');
else
break
end
end
%this lets the user know that they have dont have enough money in their account and lets them enter a different amount
while (withdrawAmount + 1.5) > Data.Balance(ac)
fprintf( 'INSUFICCIENT FUNDS Your current balance is : %.2f \n', Data.Balance(ac))
withdrawAmount = input('Please enter a different amount ');
end
%if there are suffiecient funds
if withdrawAmount + 1.5 <= Data.Balance(ac)
denominationCount(withdrawAmount); %call function to count the least number of coins and notes.
%subtract the withdrawn amount and the service charge from the
%user's account balance
Data.Balance(ac)= Data.Balance(ac)-(withdrawAmount + 1.5);
writetable(Data, 'NaiveBankData.csv'); %update the csv file with the new balance
%removing the withdrawn amount from the cash reserve
CR=CR- withdrawAmount;
%write the new cash reserve number into the cash reserve file
writematrix(CR, reserve);
fprintf('An amount of: %.2f \n has been debited from your account. ', (withdrawAmount + 1.5))
fprintf(' Your remaining balance is: %.2f \n ', Data.Balance(ac))
function posnum = getPositiveNumber()
prompt1 = 'please enter a numeric value : ';
prompt2 = 'please enter a positive value : ';
prev_was_negative = false;
while true
if prev_was_negative
prompt = prompt2;
else
prompt = prompt1;
end
p = input(prompt, 's');
vetted = regexp(p, '^(-?[0-9]+(\.[0-9]{0,2})?$)|^-?\.[0-9]{1,2}$', 'match');
if isempty(vetted)
prev_was_negative = false;
% fail to match pattern, do nothing special, loop will repeat
else
trial_num = str2double(vetted);
if trial_num < 0
prev_was_negative = true;
elseif ~isnan(trial_num)
prev_was_negative = false;
break
else
% somehow vetted number converted to nan ??
fprintf('Bug validating number. Please report input |%s|\n', p)
end
end
end
posnum = trial_num;
end
Image Analyst
on 12 Dec 2021
Of course we could fix it, but rather than us just fixing it, it would be more helpful to you to learn how to debug. So you can then set breakpoints and step through the program and look at variable values. Here is how you can do that.
Walter Roberson
on 12 Dec 2021
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
Get rid of that entire section. That section of code should start directly with
while true
withdrawAmount = getPositiveNumber();
If you want to specifically tell the user off about having too many decimal places, then edit the getPositiveNumber() function. In particular, you would give that error if
~isempty(regexp(p, '\.[0-9]{3,}'))
which matches a literal period followed by at least 3 digits.
Tariq Hammoudeh
on 12 Dec 2021
Edited: Tariq Hammoudeh
on 12 Dec 2021
Ok i edited it to the following and it does work, it doesnt let me put more than 2 decimal places, but how can i make the 3rd prompt appear when if ~isempty(regexp(p, '\.[0-9]{3,}'))
function posnum = getPositiveNumber()
prompt1 = 'please enter a numeric amount : ';
prompt2 = 'please enter a positive value : ';
prompt3= 'please limit your amount to 2 decimal places : ';
prev_was_negative = false;
while true
if prev_was_negative
prompt = prompt2;
else
prompt = prompt1;
end
p = input(prompt, 's');
vetted = regexp(p, '^(-?[0-9]+(\.[0-9]{0,2})?$)|^-?\.[0-9]{1,2}$', 'match');
if isempty(vetted)
prev_was_negative = false;
% fail to match pattern, do nothing special, loop will repeat
else
trial_num = str2double(vetted);
if trial_num < 0
prev_was_negative = true;
elseif ~isnan(trial_num)
prev_was_negative = false;
break
else
% somehow vetted number converted to nan ??
fprintf('Bug validating number. Please report input |%s|\n', p)
end
if ~isempty(regexp(p, '\.[0-9]{3,}'))
prev_was_negative = false;
end
end
end
posnum = trial_num;
end
If you cant answer me its fine, but this is my last issue for my entire program and its done
Tariq Hammoudeh
on 13 Dec 2021
I tried
if ~isempty(regexp(p, '\.[0-9]{3,}'))
disp('use 2 decimal places only')
end
and
if ~isempty(regexp(p, '\.[0-9]{3,}'))
withdrawAmount= input('use 2 decimal places only')
end
and neither worked
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
% fail to match pattern, do nothing special, loop will repeat
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
Tariq Hammoudeh
on 13 Dec 2021
Edited: Walter Roberson
on 13 Dec 2021
but when that is combined with that:
while true
withdrawAmount = getPositiveNumber(); %call function that loops an invalid withdrawal amount
if withdrawAmount > CR
fprintf('insufficient funds in ATM, please enter a different amount\n');
else
break %if amount is valid, break out of loop and continue
end
end
the withdraw amount doesnt get processed it just keeps asking for a withdraw amount
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
More Answers (2)
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
Tariq Hammoudeh
on 10 Dec 2021
i tried this but i dont need the warning message, so i changed it to:
decimalPlaces = inf;
while decimalPlaces >= 3
withdrawAmountString = input ('Please limit your entered amount to 2 numbers to the right of the decimal point : ', 's');
dotLocation = find(withdrawAmountString == '.', 1, 'last');
decimalPlaces = length(withdrawAmountString) - dotLocation;
if decimalPlaces >= 3
disp('please limit amount to 2 decimal places')
else
% Good! It's 2 or less. Now convert string to a number.
withdrawAmount = str2double(withdrawAmountString);
end
end
But the first time i enter a number with 3 decimal places it just displays the message "Please limit your entered amount to 2 numbers to the right of the decimal point" and lets me enter another amount, but the second time i enter a number with 3 decimal places it displays both messages and lets me enter an amount again. So how can i make it so that only the "Please limit your entered amount to 2 numbers to the right of the decimal point" displays each time.
Tariq Hammoudeh
on 10 Dec 2021
Also with that code it still displays the message "Please limit your entered amount to 2 numbers to the right of the decimal point" even if i only put 2 decimal place. it only continues with the code after the second time
Image Analyst
on 10 Dec 2021
Right. That's working as intended. Each time you enter 3 or more decimal places, it will notify that you did it wrong and will give you another opportunity to enter a number with 0, 1, or 2 decimal places. Isn't that what you said you wanted?
If you don't like my popup warning message, and simply want to display the confusing "invalid" with no explanation why the input is invalid, then you can confuse the user by doing 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
disp("Invalid.");
else
% Good! It's 2 or less. Now convert string to a number.
withdrawAmount = str2double(withdrawAmountString);
end
end
Frankly I think my error message is more informative than just saying "invalid" like you suggested.
Tariq Hammoudeh
on 10 Dec 2021
apologies the previous code did work i mixed something up, so thank you
Also i just wrote invalid to ask the question, thats not the message i have in my code.
Tariq Hammoudeh
on 10 Dec 2021
Is there a way to make it so that, if a letter or character is entered instead of a number, it just lets me try again again without giving an error. Because now it lets me try again but gives an error in the command window.
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
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
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
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
See Also
Categories
Find more on Startup and Shutdown in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)