Why does trunc(1) output as 0? - c++

Can someone explain me why in c++ happens such a thing:
double tmp;
... // I do some operations with tmp
// after which it has to be equal to one
cout << tmp; // prints 1
cout << trunc(tmp); // prints 0
cout << trunc(tmp*10); // prints 9
I am using this for separation part right of decimal part from the number for example if i have: 5.010 ... i want to have 0.010 .. so I am using:
double remainder = tmp - trunc(tmp);
I am posting the whole code....the suggestion with floor does not worked
short getPrecision(double num, short maxPrecision) {
// Retrieve only part right of decimal point
double tmp = fabs(num - trunc(num));
double remainder = tmp;
// Count number of decimal places
int c = 0;
while (remainder > 0 && c < maxPrecision) {
tmp *= 10;
remainder = tmp - trunc(tmp);
c++;
}
return c;
}
When I run this function for example with 5.1 the remanider is 0 instead of 1

After some calculations it has to be one? Well, it could as well be 0.99999999999999999. Floating point operations are not precise, you should always take that into account.

Please see picture at http://en.cppreference.com/w/cpp/numeric/math/trunc. The chart there explains the inconsistency with truncing 1. Probably the same applies to 10 as well
This should help you achieving what you need:
double remainder = tmp - floor(tmp);

Related

Error with two credit card numbers. Identifies the number as the wrong credit card type

These are my current errors, I think I did something wrong with the maths but everything I tried didn't work.
Ps: Sorry if my question's formatting is bad, first time using stackflow.
:) credit.c exists
:) credit.c compiles
:) identifies 378282246310005 as AMEX
:) identifies 371449635398431 as AMEX
:) identifies 5555555555554444 as MASTERCARD
:) identifies 5105105105105100 as MASTERCARD
:) identifies 4111111111111111 as VISA
:) identifies 4012888888881881 as VISA
:) identifies 4222222222222 as VISA
:) identifies 1234567890 as INVALID
:) identifies 369421438430814 as INVALID
:) identifies 4062901840 as INVALID
:) identifies 5673598276138003 as INVALID
:( identifies 4111111111111113 as INVALID
expected "INVALID\n", not "VISA\n"
:( identifies 4222222222223 as INVALID
expected "INVALID\n", not "VISA\n"
#include <cs50.h>
#include <math.h>
// Prompt user for credit card number
int main(void)
{
long credit_card, credit_number;
do
{
credit_card = get_long("Enter credit card number: ");
}
while (credit_card < 0);
credit_number = credit_card;
// Calculate total number of digits
int count = (credit_number == 0) ? 1 : (log10(credit_number) + 1);
int summation = 0;
while (credit_number == 0)
{
int x = credit_number % 10; summation += x;
int y = 2 * ((credit_number / 10) % 10);
int r = (y % 10) + floor((y / 10) % 10); summation += r; credit_number /= 100;
}
string card;
// Identify which card type you get after inputing your credit card number
int test = cc / pow(10, count - 2);
if ((count == 13 || count == 16) && test / 10 == 4)
{
card = "VISA";
}
else if (count == 16 && test >= 51 && test <= 55)
{
card = "MASTERCARD";
}
else if (count == 15 && (test == 34 || test == 37))
{
card = "AMEX";
}
else
{
card = "INVALID";
}
// Final verification
if (sum % 10 == 0)
{
printf("%s\n", card);
}
else
{
printf("INVALID\n");
}
}```
Your algorithm is maybe not fully correct. I would therefore propose a different approach. You can look at each single digit in a loop. And, you can also do the whole checksum calculation in one step.
I will show you how to do and explain the algorithm behind it.
BTW. Chosing the right algorithm is always the key for success.
So, first we need to think on how we can extract digits from a number. This can be done in a loop by repeating the follwoing steps:
Perform a modulo 10 division to get a digit
Do a integer division by 10
Repeat
Let us look at the example 1234.
Step 1 will get the 4 -- (1234 % 10 = 4)
Step 2 will convert original number into 123 -- (1234 / 10 = 123)
Step 1 will get the 3 -- (123 % 10 = 3)
Step 2 will convert the previous number into 12 -- (123 / 10 = 12)
Step 1 will get the 2 -- (12 % 10 = 2)
Step 2 will convert the previous number into 1 -- (12 / 10 = 1)
Step 1 will get the 1 -- (1 % 10 = 1)
Step 2 will convert the previous number into 0 -- (1 / 10 = 0)
Then the loop stops. Additionally we can observe that the loop stops, when the resulting divided becomes 0. And, we see addtionally that the number of loop executions is equal to the number of digits in the number. But this is somehow obvious.
OK, then let us look, what we learned so far
while (creditCardNumber > 0) {
unsigned int digit = creditCardNumber % 10;
creditCardNumber /= 10;
++countOfDigits;
}
This will get all digits and count them.
Good. Lets go to next step.
For later validation and comparison purpose we need to get the most significant digit (the first digit) and the second most significant digit (the second digit) of the number.
For this, we define 2 variables which will hold the number. We simply assign the current evaluated digit (and override it in each loop execution) to the "mostSignificantDigit". At the end of the loop, we will have it in our desired variable.
For the "secondMostSignificantDigit" we will simple copy the "old" or "previous" value of the "mostSignificantDigit", before assigning a new value to "mostSignificantDigit". With that, we will always have both values available.
The loop looks now like this:
while (creditCardNumber > 0) {
const unsigned int digit = creditCardNumber % 10;
secondMostSignificantDigit = mostSignificantDigit;
mostSignificantDigit = digit;
creditCardNumber /= 10;
++countOfDigits;
}
OK, now we come to the maybe more complex part. The cheksum. The calculation method is.
Start with the least significant (the last) digit
Do not multiply the digit, which is equivalent with multiplying it with 1, and add it to the checksum
Goto the next digit. Multiply it by 2. If the result is greater than 10, then get again the single digits and add both digits to the checksum
Repeat
So, the secret is, to analyze the somehow cryptic specification, given here. If we start with the last digit, we do not multiply it, the next digit will be multiplied, the next not and so on and so on.
To "not multiply" is the same as multiplying by 1. This means: In the loop we need to multiply alternating with 1 or with 2.
How to get alternating numbers in a loop? The algorithm for that is fairly simple. If you need alternating numbers, lets say, x,y,x,y,x,y,x..., Then, build the sum of x and y and perform the subtratcion "value = sum - value". Example:
We need alternating values 1 and 2. The sum is 3. To get the next value, we subtract the current value from the sum.
initial value = 1
sum = 3
current value = initial value = 1
next value = 3 - 1 = 2. Current value = 2
next value = 3 - 2 = 1. Current value = 1
next value = 3 - 1 = 2. Current value = 2
next value = 3 - 2 = 1. Current value = 1
next value = 3 - 1 = 2. Current value = 2
next value = 3 - 2 = 1. Current value = 1
. . .
Good, now we understand, how to make alternating values.
Next, If we multiply a digit with 2, then the maximum result maybe a 2 digit value. We get the single digits with a modulo and an integer division by 10.
And, now important, it does not matter, if we multiply or not, because, if we do not multiply, then the upper digit will always be 0. And this will not contribute to the sum.
With all that, we can always do a multiplication and always split the result into 2 digits (many of them having the upper digit 0).
The result will be:
checkSum += (digit * multiplier) % 10 + (digit * multiplier) / 10;
multiplier = 3 - multiplier;
An astonishingly simple formula.
Next, if we know C or C++ we also know that a multiplication with 2 can be done very efficiently with a bit shift left. And, additionally, a "no-multiplication" can be done with a bit shift 0. That is extremely efficient and faster than multiplication.
x * 1 is identical with x << 0
x * 2 is identical with x << 1
For the final result we will use this mechanism, alternate the multiplier between 0 and 1 and do shifts.
This will give us a very effective checksum calculation.
At the end of the program, we will use all gathered values and compare them to the specification.
Thsi will lead to:
int main() {
// Get the credit card number. Unfortunately I do not know CS50. I use the C++ standard iostream lib.
// Please replace the following 4 lines with your CS50 equivalent
unsigned long long creditCardNumber;
std::cout << "Enter credit card number: ";
std::cin >> creditCardNumber;
std::cout << "\n\n";
// We need to count the number of digits for validation
unsigned int countOfDigits = 0;
// Here we will calculate the checksum
unsigned int checkSum = 0;
// We need to multiply digits with 1 or with 2
unsigned int multiplier = 0;
// For validation purposes we need the most significant 2 digits
unsigned int mostSignificantDigit = 0;
unsigned int secondMostSignificantDigit = 0;
// Now we get all digits from the credit card number in a loop
while (creditCardNumber > 0) {
// Get the least significant digits (for 1234 it will be 4)
const unsigned int digit = creditCardNumber % 10;
// Now we have one digit more. In the end we will have the number of all digits
++countOfDigits;
// Simply remember the most significant digits
secondMostSignificantDigit = mostSignificantDigit;
mostSignificantDigit = digit;
// Calculate the checksum
checkSum += (digit << multiplier) % 10 + (digit << multiplier) / 10;
// Multiplier for next loop
multiplier = 1 - multiplier;
creditCardNumber /= 10;
}
// Get the least significant digit of the checksum
checkSum %= 10;
// Validate all calculated values and show the result
if ((0 == checkSum) && // Checksum must be correct AND
(15 == countOfDigits) && // Count of digits must be correct AND
((3 == mostSignificantDigit) && // Most significant digits must be correct
((4 == secondMostSignificantDigit) || (7 == secondMostSignificantDigit)))) {
std::cout << "AMEX\n";
}
else if ((0 == checkSum) && // Checksum must be correct AND
(16 == countOfDigits) && // Count of digits must be correct AND
((5 == mostSignificantDigit) && // Most significant digits must be correct
((secondMostSignificantDigit > 0) && (secondMostSignificantDigit < 6)))) {
std::cout << "MASTERCARD\n";
}
else if ((0 == checkSum) && // Checksum must be correct AND
((16 == countOfDigits) || (13 == countOfDigits)) && // Count of digits must be correct AND
((4 == mostSignificantDigit))) { // Most significant digit must be correct
std::cout << "VISA\n";
}
else {
std::cout << "INVALID\n";
}
return 0;
}
What we learn with this example, is integer division and modulo division and the smart usage of the identity element for binary operations.
In case of questions, please ask
Just to be complete, I will show you a C++ solution, based on a std::string and using modern C++ elements and algorithms.
For example, the whole checksum calculation will be done with one statement. The whole program does not contain any loop.
#include <iostream>
#include <string>
#include <regex>
#include <numeric>
int main() {
// ---------------------------------------------------------------------------------------------------
// Get user input
// Inform user, what to do. Enter a credit card number. We are a little tolerant with the input format
std::cout << "\nPlease enter a credit card number:\t";
// Get the number, in any format from the user
std::string creditCardNumber{};
std::getline(std::cin, creditCardNumber);
// Remove the noise, meaning, all non digits from the credit card number
creditCardNumber = std::regex_replace(creditCardNumber, std::regex(R"(\D)"), "");
// ---------------------------------------------------------------------------------------------------
// Calculate checksum
unsigned int checksum = std::accumulate(creditCardNumber.rbegin(), creditCardNumber.rend(), 0U,
[multiplier = 1U](const unsigned int sum, const char digit) mutable -> unsigned int {
multiplier = 1 - multiplier; unsigned int value = digit - '0';
return sum + ((value << multiplier) % 10) + ((value << multiplier) / 10); });
// We are only interested in the lowest digit
checksum %= 10;
// ---------------------------------------------------------------------------------------------------
// Validation and output
if ((0 == checksum) && // Checksum must be correct AND
(15 == creditCardNumber.length()) && // Count of digits must be correct AND
(('3' == creditCardNumber[0]) && // Most significant digits must be correct
(('4' == creditCardNumber[1]) || ('7' == creditCardNumber[1])))) {
std::cout << "AMEX\n";
}
else if ((0 == checksum) && // Checksum must be correct AND
(16 == creditCardNumber.length()) && // Count of digits must be correct AND
(('5' == creditCardNumber[0]) && // Most significant digits must be correct
((creditCardNumber[1] > '0') && (creditCardNumber[1] < '6')))) {
std::cout << "MASTERCARD\n";
}
else if ((0 == checksum) && // Checksum must be correct AND
((16 == creditCardNumber.length()) || (13 == creditCardNumber.length())) && // Count of digits must be correct AND
(('4' == creditCardNumber[0]))) { // Most significant digit must be correct
std::cout << "VISA\n";
}
else {
std::cout << "INVALID\n";
}
return 0;

CodeSignal isLucky task c++

Started to practice C++ by trying to do some tasks in CodeSignal, but I can’t figure it out why it has an output which is always false. Saw a similar answer to this task but didn’t want to copy and paste without understanding where the error is.
Ticket numbers usually consist of an even number of digits. A ticket number is considered lucky if the sum of the first half of the digits is equal to the sum of the second half.
Example:
For n = 1230, the output should be isLucky(n) = true
For n = 239017, the output should be isLucky(n) = false
Code:
bool isLucky(int n) {
string convert = to_string(n); // to convert from string to int
int sizehalbe = convert.size() / 2; //divide into 2 halfs
//Stor each half
string h1 = convert.substr(0, sizehalbe-1);
string h2 = convert.substr(sizehalbe, convert.size()-1);
int sum1=0, sum2=0; //Calculate the halfs
for(int i=0;i<h1.length();i++)
{
sum1 += int(h1.at(i));
}
for(int j=0;j<h2.length();j++)
{
sum2 += int(h2.at(j));
}
if(sum1 == sum2)
return true;
else
return false;
}
(1). Foremost your h1 always miss one digit so instead of
h1 = convert.substr(0, sizehalbe-1);
that's the only main issue your code has, convert should be gone till sizehalbe
string h1 = convert.substr(0, sizehalbe);
(2). whenever you typecast from character to integer, check what it gives
cout<<int('0'); will give you 48 instead of 0.
in particular, this case it's not changed your main output
(due to both sum1 & sum2 will get higher result than what actually should be,
but get same level of higher.)
sum½ += int(h½.at(i)) - 48;
(3). you can optimize your last condition.
when boolean result is depending on condition you can do
return (sum1 == sum2);

I need to get a random number in the range from a to b with n decimal places

I need a function that returns me a random number with n decimal places
Example:
int aleatorio(int li, int ls)
{
return rand()%(ls+1-li)+li;
}
What i want is:
float new_random(int start, int final, int number_decimals)
{
return // What should I write here?
}
if I would call this function 5 times like this::
new_random(0, 5, 4);
The exit would be:
0.2344
3.4356
2.8435
4.2435
I do not want to use this, because I need numbers of 4 exact decimal places since I will not use them to print, but you will have others:
cout << setprecision(4) << 4.24359675967 << endl; //I do not want this
I need numbers of 4 exact decimal places
Then you cannot use finite precision binary floating point (i.e. float, double or long double) because those types cannot exactly represent all of the values with 4 decimal places.
A solution is to use arbitrary precision floating point, and another is to use fixed point. C++ standard doesn't provide arbitrary precision types nor fixed point types. Another approach is to give up the requirement of exactly representing those values and accept the almost exact values that are achievable with limited precision.
Try this for a Java solution. Multiply the start and finish by 1000, generating ints between the range and then divide the resultant number by 1000 as a double.
int start = 20;
int finish = 30;
int count = 10;
Random r = new Random();
r.ints(start * 1000, finish * 1000).filter(n -> n % 10 != 0)
.limit(count).mapToDouble(n -> n / 1000.)
.forEach(System.out::println);
prints something like this.
21.186
26.983
25.345
20.764
27.911
21.139
24.679
27.722
29.443
28.675
Or as a method supplying the starting number, ending number and precision.
for (int i = 0; i < 10; i++) {
System.out.println(newRandom(start,finish,4));
}
static Random r = new Random();
public static Double newRandom(int start, int finish, int precision) {
int f = (int)Math.pow(10,precision);
return r.ints(start * f, finish * f).filter(n -> n % 10 != 0)
.limit(1).mapToDouble(n -> n / (double)f).findFirst().getAsDouble();
}
Prints something like this.
28.4444
25.0259
29.5611
25.6445
25.4977
28.5124
28.9709
23.4835
27.9766
23.9438
You can generate an integer number N between start and final * 10^number_decimals and then return N / 10^number_decimals
Eg. start = 0, final = 5, number_decimals = 4 ==> N in [0 - 50000] ==> N/10000 in [0.0000 - 5.0000]
float new_random(int start, int final, int number_decimals) {
return aleatorio(start, final*pow10(number_decimals))/number_decimals;
}
You can define pow10 as:
int pow10(int p) {
if (p == 0) return 1;
else return 10 * pow10(p-1);
}

Why does the following program gives wrong answer when I remove "+ mod" from statement check . Problem link: https://www.codechef.com/problems/FFC219B

The statement check is where I don't understand why it shows wrong answer on submission when I write "sum = (solution[R]-solution[L-1])%mod;" instead. Here I have not added mod within the bracket. I don't see how the answer changes by adding a value of taking the mod of same. Problem code in codechef: https://www.codechef.com/problems/FFC219B
#include<iostream>
#define ll long long
#define mod 1000000007 //the modulus we need to take for the final answer
#define endl "\n"
using namespace std;
long long solution[100007] = {0}; //Initialising all the values with zero
int main(){
ios_base :: sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solution[0] = 0;
ll a1=1,a2=2,a3=3,a4=4; //The variable initialising as per the problem
for(int i = 1;i <= 100007;i++){
ll k=(a1 * a2) % mod * a3 % mod * a4 % mod;
solution[i] = (solution[i-1]+k)%mod; //Adding the previous values as we are to find the sum in range
a1++;
a2++;
a3++;
a4++;
}
int t; //Taking input for number of test cases
cin>>t;
while(t-->0)
{
int L,R;
cin>>L>>R; //Taking the range input
long long sum = 0;
sum = (solution[R]-solution[L-1] + mod)%mod; //statement check & final answer
cout<<sum<<endl;
}
return 0;
}
The program can give the incorrect answer since the correct answer must always be a positive - not a negative - number.
When you subtract consecutive modulo values, the result may well be negative even though the numbers themselves are increasing (eg, (4^3)%10 - (4^2)%10 = 64%10 - 16%10 = 4-6 = -2), . This means “solution[R]-solution[L-1]” may also well be negative, which means “(solution[R]-solution[L-1]) % mod” will also be negative - although clearly the answer (the number of people affected) must always be positive.
So adding the mod value in this fashion ensures that the result will always be positive.

How can I obtain the cube root in C++?

I know how to obtain the square root of a number using the sqrt function.
How can I obtain the cube root of a number?
sqrt stands for "square root", and "square root" means raising to the power of 1/2. There is no such thing as "square root with root 2", or "square root with root 3". For other roots, you change the first word; in your case, you are seeking how to perform cube rooting.
Before C++11, there is no specific function for this, but you can go back to first principles:
Square root: std::pow(n, 1/2.) (or std::sqrt(n))
Cube root: std::pow(n, 1/3.) (or std::cbrt(n) since C++11)
Fourth root: std::pow(n, 1/4.)
etc.
If you're expecting to pass negative values for n, avoid the std::pow solution — it doesn't support negative inputs with fractional exponents, and this is why std::cbrt was added:
std::cout << std::pow(-8, 1/3.) << '\n'; // Output: -nan
std::cout << std::cbrt(-8) << '\n'; // Output: -2
N.B. That . is really important, because otherwise 1/3 uses integer division and results in 0.
in C++11 std::cbrt was introduced as part of math library, you may refer
include <cmath>
std::pow(n, 1./3.)
Also, in C++11 there is cbrt in the same header.
Math for Dummies.
The nth root of x is equal to x^(1/n), so use std::pow. But I don't see what this has to with operator overloading.
Just to point this out, though we can use both ways but
long long res = pow(1e9, 1.0/3);
long long res2 = cbrt(1e9);
cout<<res<<endl;
cout<<res2<<endl;
returns
999
1000
So, in order to get the correct results with pow function we need to add an offset of 0.5 with the actual number or use a double data type i.e.
long long res = pow(1e9+0.5, 1.0/3)
double res = pow(1e9, 1.0/3)
more detailed explanation here C++ pow unusual type conversion
Actually the round must go for the above solutions to work.
The Correct solution would be
ans = round(pow(n, 1./3.));
The solution for this problem is
cube_root = pow(n,(float)1/3);
and you should #include <math.h> library file
Older standards of C/C++ don't support cbrt() function.
When we write code like cube_root = pow(n,1/3); the compiler thinks 1/3 = 0 (division problem in C/C++), so you need to do typecasting using (float)1/3 in order to get the correct answer
#include<iostream.h>
#include<conio.h>
#include<math.h>
using namespace std;
int main(){
float n = 64 , cube_root ;
clrscr();
cube_root = pow(n , (float)1/3);
cout<<"cube root = "<<cube_root<<endl;
getch();
return 0;
}
cube root = 4
You can try this C algorithm :
// return a number that, when multiplied by itself twice, makes N.
unsigned cube_root(unsigned n){
unsigned a = 0, b;
for (int c = sizeof(unsigned) * CHAR_BIT / 3 * 3 ; c >= 0; c -= 3) {
a <<= 1;
b = 3 * a * (a + 1) + 1;
if (n >> c >= b)
n -= b << c, ++a;
}
return a;
}
I would discourage any of the above methods as they didn't work for me. I did pow(64, 1/3.) along with pow(64, 1./3.) but the answer I got was 3
Here's my logic.
ans = pow(n, 1/3.);
if (pow(ans, 3) != n){
ans++;
}