Prateek Krishna Ответов: 4

Почему он не работает с n=27 и 216?..


чтобы узнать, является ли число совершенным кубом или нет .

Что я уже пробовал:

#include <bits/stdc++.h>
using namespace std;

int iscqrt(int x) 
{   
  
   double sr = cbrt(x); 
  return (sr - floor(sr) == 0); 
} 
int main() {
	int n;
	cin>>n;
	if(iscqrt(n))
	cout<<"perfect cube";
	else
	cout<<"no";
	
}

Richard MacCutchan

Отлично работает, когда я запускаю его, для обоих значений.

Prateek Krishna

27 - это идеальный куб. таким образом, он должен давать идеальный куб в качестве вывода, но он не дает никакого результата .

Richard MacCutchan

Ну, я запустил ваш код, и он говорит "идеальный куб" для 27 и 216. Я подозреваю, что фактический код, который вы запускаете, каким-то образом отличается.

4 Ответов

Рейтинг:
6

Patrice T

Цитата:
Почему он не работает с n=27 и 216?..

Это потому что double это "двоичные числа с плавающей запятой", и они не являются точными значениями.
Арифметика с плавающей запятой - Википедия[^]
Двоичные дроби и плавающая точка - двоичный учебник[^]

Решение состоит в том, чтобы не использовать числа с плавающей запятой, как в решении 3.


Рейтинг:
33

k5054

Вы должны взглянуть на то, что sr -float(sr) evaluates to. It's not zero, bet very close. On my system I get 4.44089e-16. Why would that be. This has to do with how computers represent floating point numbers (float, double, long double). In particular, some base-10 numbers cannot be represented to 100% accuracy. There is also the limitation of the precision of floating point numbers. As an example, in base-10 even 1.0/3.0 cannot be represented accurately, so the calculation (1.0/3.0)*3.0 expressed to 10 digits of precision returns 0.999999999, not 1.0. Combine those 2 things together and often times what we expect to happen when working with floating point numbers is wrong, when dealing with computers. In particular, comparison for equality, as shown here, doesn't always work as expected. In general, you'll want to know how accurate you need to be and compare within that accuracy. You might, for example, use this return( fabs(sr - floor(sr)) < 1e-6) вместо сравнения с 0.0


KarstenK

вы пропустили знак "-" в "1e6". :-O

Рейтинг:
21

Dave Kreskowiak

Код работает нормально.

Это немного запутанно, и ваш тип возврата для функции "iscqrt" должен быть bool, а не int, но в остальном он отлично работает как для ваших тестовых случаев, так и для других.


Рейтинг:
16

OriginalGriff

Двойники могут быть забавными числами: они не очень хорошо "совпадают" со своими десятичными эквивалентами, поэтому они в лучшем случае являются приближением к числу, хотя и очень точным приближением.
Вместо того чтобы возиться с ними floor, возьмите кубический корень числа, преобразуйте его в целое число и сравните его с оригиналом:

int iscqrt(int x) 
   {   
   int sr = (int) cbrt(x); 
   return ((int) x == sr * sr * sr); 
   } 


Richard MacCutchan

Я запустил код OP, и оба числа дали истинный результат.

OriginalGriff

Может быть, это компилятор / библиотека, которую он использует?