Prevent non-integer division - c++

I am writing a Qt application as a hobby that prompts users to answer basic arithmetic questions using the add, minus, multiply and divide operators. The questions are generated, and everytime a question is correctly answered new operands are generated and a new operator used.
In some cases, a question might come up as '4 / 5' or '3 / 2' which implies the answer is a non-integer value to be entered. A requirement that I've set is that there are no irrational numbers in the program at all: that means no irrational answers, operands, operators or whatnot.
In my class I have a validator function which validates every question that's generated.
void ArQuestion::validate()
{
int answer = getActualAnswer();
if ((pOperand2 % 2 != 0) ||
pOperator == operators::DIVIDE)
{
if (static_cast<int>(answer) != answer)
{
generate();
}
}
}
Where getActualAnswer() retrieves the actual answer of the question.
Unfortunately my validator isn't working, and presumably the static_cast trick isn't working either. When I run the program there are still questions that ask irrational division questions (questions which produce irrational answers). What I want the validator to do is function in a way that prevents questions (only under division questions) from asking irrationally such as '3 / 4' or '7 / 9'. If the question is irrational, then it should generate a new question.
My question is thus: what algorithm is there for me to prevent non-integer division questions from being asked?

This should be fairly reliable,
bool quotient_is_integral(double n, double d)
{
double dummy;
return std::modf(n/d, &dummy) == 0.0;
}

What you're looking for is a way to determine if a division problem returns an integer answer, here's a small function to do it.
#include <iostream>
#include <cmath>
#include <limits>
bool check(double l, double r)
{
double real_answer = l / r;
int target_answer = static_cast<int>(real_answer);
double checked_answer = target_answer;
if(std::fabs(real_answer - checked_answer) > std::numeric_limits<double>::min())
{
std::cout << "Invalid.\n";
return false;
}
return true;
}

Related

Pre and Post Condition from Stroustrup's book

In chapter 5.10.1 of Programming: Principles and Practice using C++, there is a "Try this" exercise for debugging for bad input of an area. The pre-conditions are if the the inputs for length and width are 0 or negative while the post-condition is checking if the area is 0 or negative. To quote the problem, "Find a pair of values so that the pre-condition of this version of area holds, but the post-condition doesn’t.". The code so far is:
#include <iostream>
#include "std_lib_facilities.h"
int area (int length, int width) {
if (length <= 0 || width <= 0) { error("area() pre-condition"); }
int a = length * width;
if(a <= 0) { error("area() post-condition"); }
return a;
}
int main() {
int a;
int b;
while (std::cin >> a >> b) {
std::cout << area(a, b) << '\n';
}
system("pause");
return 0;
}
While the code appears to work, I can't wrap my head around what inputs will get the pre-condition to succeed yet will trigger the post-condition. So far I have tried entering strings into one of the inputs but that just terminates the program and tried looking up the ascii equivalent to 0, but same result as well. Is this supposed to be some sort of trick question or am I missing something?
Consider using large values for the input so that the multiplication overflows.
Numbers which when multiplied cause signed overflow will possibly cause the value to be negative and certainly cause the result to be incorrect.
Exactly what values cause integer overflow will depend on your architecture and compiler, but the gist is that multiplying two 4 byte integers will result in an 8 byte value, which can not be stored in a 4 byte integer.
I tried this, and seems like this works: area(1000000,1000000);
The output was: -727379968

Arithmetic Error When Converting String to Double

I'm writing a function to convert a user provided string into a double. It works quite well for certain values, but fails for others. For example
string_to_double("123.45") = 123.45
string_to_double(12345) = 12345
but
string_to_double(123.4567) = 123.457
I'm fairly certain that this is some kind of round off error, but I'm not using approximations nor am I using very small or large values. My question is two-fold why am I getting these strange results and how can I change my code to get more accurate results? I'm also doing this as a personal challenge, so suggestions to use methods such as std::stod are not helpful. I believe the problem occurs in the second for-loop, but I felt it was wise to include the entire method because if I missed something it isn't that much extra code to read.
My Code
template <class T>
double numerical_descriptive_measures<T>::string_to_double(std::string user_input)
{
double numeric_value = 0;//Stores numeric value of string. Return value.
int user_input_size = user_input.size();
int power = 0;
/*This loop is for the characteristic portion of the input
once this loop finishes, we know what to multiply the
characterstic portion by(e.g. 1234 = 1*10^3 + 2*10^2 + 3*10^1 + 4)
*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] == '.')
break;
else
power++;
}
/*This loop is for the mantissa. If this portion is zero,
the loop doesn't execute because i will be greater than
user_input_size.*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] != '.')
{
numeric_value += ((double)user_input[i] - 48.0)*pow(10,power-i-1);
}
else
{
double power = -1.0;
for(int j = i+1;j < user_input_size;j++)
{
numeric_value += ((double)user_input[j] - 48.0)*pow(10.0,power);
power = power-1.0;
}
break;
}
}
return numeric_value;
}
The problem is not that you are producing the wrong floating point value, the problem is that you are printing it with insufficient precision:
std::cout<<data<<std::endl
This will only print about six digits of precision. You can use std::setprecision or other methods to print more.
Your code is not producing an incorrect value for "123.4567" but it will produce incorrect values in general. For example, string_to_double("0.0012") produces (on Visual Studio 2015)
0.0012000000000000001117161918529063768801279366016387939453125
but the correct answer is
0.00119999999999999989487575735580549007863737642765045166015625
(You would have to print them to 17 significant digits to tell the difference.)
The problem is that you can't use floating-point to convert to floating-point -- it does not have enough precision in general.
(I've written a lot about this on my site; for example, see http://www.exploringbinary.com/quick-and-dirty-decimal-to-floating-point-conversion/ and http://www.exploringbinary.com/decimal-to-floating-point-needs-arbitrary-precision/ .)

Percent of correct answers program challenge

I'm having trouble with the output of my program, the txt files show that the student got 3 answers wrong, but it keeps giving me 0% for percent of correct answers.
The challenge I was given is:
"One of your professors has asked you to write a program to grade her final exams,
which consist of only 20 multiple-choice questions. Each question has one of four possible answers: A, B, C, or D. The file CorrectAnswers.txt contains the correct answers for
all of the questions, with each answer written on a separate line. The first line contains
the answer to the first question, the second line contains the answer to the second question, and so forth.
Write a program that reads the contents of the CorrectAnswers.txt file into a char
array, and then reads the contents of another file, containing a student’s answers, into
a second char array.
The program should determine the number of questions that the student
missed, and then display the following:
• A list of the questions missed by the student, showing the correct answer and the
incorrect answer provided by the student for each missed question
• The total number of questions missed
• The percentage of questions answered correctly. This can be calculated as
Correctly Answered Questions ÷ Total Number of Questions
• If the percentage of correctly answered questions is 70% or greater, the program
should indicate that the student passed the exam. Otherwise, it should indicate
that the student failed the exam.
This is the code I have so far, thanks in advance for any suggestions!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
const int size=20;
static int count=0;
string correctAnswers[size];
string studentAnswers[size];
ifstream inFileC;
inFileC.open("c:/Users/levi and kristin/Desktop/CorrectAnswers.txt");
if (inFileC)
{
for (int i=0;i<20;i++)
{
inFileC>>correctAnswers[i];
}
}
else
{
cout<<"Unable to open \"CorrectAnswers.txt\""<<endl;
cout<<"Please check file location and try again."<<endl<<endl;
}
inFileC.close();
ifstream inFileS;
inFileS.open("c:/Users/levi and kristin/Desktop/StudentAnswers.txt");
if (inFileS)
{
for (int t=0;t<20;t++)
{
inFileS>>studentAnswers[t];
}
}
else
{
cout<<"Unable to open \"StudentAnswers.txt\""<<endl;
cout<<"Please check file location and try again."<<endl<<endl;
}
inFileS.close();
for (int k=0;k<20;k++)
{
if (correctAnswers[k]!=studentAnswers[k])
{
cout<<endl<<"Correct Answer: "<<correctAnswers[k];
cout<<endl<<"Student Answer: "<<studentAnswers[k]<<endl;
count++;
}
}
int percent=((20-count)/20)*100;
cout<<endl<<"Number of missed questions: "<<count;
cout<<endl<<"Percent of correctly answered questions: "<<percent<<"%";
if (percent>=70)
{
cout<<endl<<endl<<"********"<<endl<<"**Pass**"<<endl<<"********"<<endl<<endl;
}
else
{
cout<<endl<<endl<<"********"<<endl<<"**Fail**"<<endl<<"********"<<endl<<endl;
}
return 0;
}
Integer division will yield 0 for everything but a perfect score. Use floating-point division instead:
int percent = ((double)(20-count) / 20) * 100;
Note that (double)(20-count) casts the value (20-count) into a double-precision floating-point number. Once the whole expression has been evaluated, it gets coerced back to an integer because you're assigning the value to an int.
Integer divide always rounds towards zero, so (20 - count)/20 will be zero if count is greater than 0.
Do not need floating point, this will do the trick:
int percent = 5 * ( 20 - count );

Comparing double error C++

recently I bump into a problem while comparing a double in an if statement. I was trying to cout the number of whole numbers in a double. Being a beginner, I am not sure what gone wrong in my code.
This is my code:
#include <iostream>
using namespace std;
int main(){
int x=0;//convert double to int
long double Out;//Result
long double In=10;//Input double
//Loop Begin
while(In>0){
x=In;//convert double to int
Out= (x/In);//Out(test if whole number, will return 1)
//test for 1
////////////////
if(Out == 1 ){
cout<<"[Whole Number] ";
}
////////////////
//test end
cout<<"In :"<<In<<", ";
cout<<"X :"<<x<<", ";
cout<<"Out :"<<Out<<endl;
In-=0.1;//decrease to finish loop (eventually)
}
//Loop End
cin.get();
return 0;
}
This program will test and output the whole numbers in the double (In). I realized that the accuracy of the double was affecting the if statement which is why I can't get the "[Whole Number]" result. Although I found out that if I used (0.9999) in "if(Out >= 0.9999)" the comparison would work. But I am not sure of a solution, please help! Much appreciated!
Your while loop never stops , its a infinite loop . You are not doing anything with the value of "In" in the while loop hence it will always be greater than 0 ,therefore a infinite loop .
You should probably approach the problem more directly with modf:
double int_part, frac_part;
frac_part = std::modf(in, &int_part);
if (frac_part == 0) {
// int_part contains integer value.
} else {
// process the double non-integer floating point value.
}
Your code works perfectly fine. If you subtract 0.1 from 10.0, then chances are that the result is not an integer due to rounding errors, and your code tells you exactly that. The code isn't wrong, your expectations are wrong.
if (Out >= 0.9999)
is obviously not a solution, because it will always be true if In >= 10000.0.
Do to the way floating point numbers are converted to binary representation by the computer they are inherently inaccurate and thus make logical comparisons somewhat challenging (http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems). When performing such comparisons to floating point numbers you typically will do so utilizing an epsilon constant (http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm) that represents the maximum acceptable error in the comparison. In your case you need to select a suitable value for epsilon (say .000001). Then change your comparison to:
if(abs(out - 1) < epsilon){ //Take the difference between out and 1
cout<<"[Whole Number]"; //If it is "close enough" print to console
}
I am more of a Java guy but I believe you will need #include stdlib.h to utilize the abs() function.
Hope that helps!
Try using the modulus operator: http://www.cprogramming.com/tutorial/modulus.html
Something like if(In % 1 == 0) should work.

C++ total beginner needs guidance [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
yesterday,we had to solve problems at the codeforces contest
I couldn't solve this problem since I am a total beginner.
http://codeforces.com/contest/353/problem/A
I used this algorithm, but something is wrong with it. I think it should print s or f, however it prints nothing. it just auto closes. Even when I added an input to stop instant close
#include <cstdlib>
#include <iostream>
using namespace std;
int main(){
int y=0;
int x=0;
int f;
int a;
cin >> a;
int s;
s = 0;
int number [a][a];
for(int i = 0;i<a;i++){
cin >> number[i][0] >> number[i][1];
x += number[i][0];
y += number[i][1];
}
for(int i = 0;i<a;i++){
if(x%2==0 && y%2==0){
return s;
}else if(y%2!=0 && x%2==0){
f = -1;
return f;
}else if(y%2==0 && x%2!=0){
f = -1;
return f;
}else{
y+= number[i][0];
x+= number[i][1];
s++;
}
}
int g;
if(f!=-1){
cout << s;
}else{
cout << f;
}
}
As Angew said, the return statements are incorrect and causing you to exit your main. You want to replace this by a break; to exit the loop but not the function.
I have not spent effort in trying to understand your algorithm, but at first glance it looks more complicated than it should be.
From my understanding of the problem, there are 3 possibilities:
the totals of the upper halves and the lower halves are already even (so nothing needs to be done)
the totals of the upper halves and the lower halves cannot be made even (so no solution exists)
just one Domino needs to be rotated to get the totals of the upper halves and the lower halves to be even (so the time needed is 1 second)
I base this on the fact that adding only even numbers always gives an even result, and adding an even number of odd numbers also always gives an even result.
Based on this, instead of having a 2-dimensional array like in your code, I would maintain 2 distinct arrays - one for the upper half numbers and the other for the lower half numbers. In addition, I would write the following two helper functions:
oddNumCount - takes an array as input; simply returns the number of odd numbers in the array.
oddAndEvenTileExists - takes 2 arrays as input; returns the index of the first tile with an odd+even number combination, -1 if no such tile exists.
Then the meat of my algorithm would be:
if (((oddNumCount(upper_half_array) % 2) == 0) && ((oddNumCount(lower_half_array) % 2) == 0))
{
// nothing needs to be done
result = 0;
}
else if (((oddNumCount(upper_half_array) - oddNumCount(lower_half_array)) % 2) == 0)
{
// The difference between the number of odd numbers in the two halves is even, which means a solution may exist.
// A solution really exists only if there exists a tile in which one number is even and the other is odd.
result = (oddAndEvenTileExists(upper_half_array, lower_half_array) >= 0) ? 1 : -1;
}
else
{
// no solution exists.
result = -1;
}
If you wanted to point out exactly which tile needs to be rotated, then you can save the index that "oddAndEvenTileExists" function returns.
You can write the actual code yourself to test if this works. Even if it doesn't, you would have written some code that hopefully takes you a little above "total beginner".