Simplifying Radicals Program

Pages: 12
hello, I have a homework question which is to create a program that lets the user enter the degree of the radical and the value under the root and write the radical in simplest form.
Sample output:
Enter the degree of the root: 3
Enter the values under the root:16
Simplified radical: 2 * degree 3 root 2
I was stuck on this question for quite a long time and I am still not able to code this program. It's kinda urgent so I would really appreciate some help. Thanks!
show some code.
#include <iostream>
#include <cmath>
using namespace std;

int main(){
int degree,a,b,z=1;
double root,y,x;
cout << "Please enter the degree of the root: ";
cin >> degree;
while (degree<2){
cout << "Please enter a degree greater than or equal to 2: ";
cin >> degree;
}
cout << "Please enter the value under the root: ";
cin >> x;
while (x<0){
cout << "Please enter a positve number as the value: ";
cin >> x;
}
root=1.0/degree;
y=pow(x,root);
z=pow(y,degree);

if (z==x){
cout << "The answer is " << y;
return 0;
}
for (int i=x/2;i>0;i--){
a=pow(i,1/degree);
if (pow(a,degree)==i){
cout << "The simplifed radical is " << a << " * degree " << degree << " root " << x/i;
return 0;
}
}



}

there are probably a lot of errors in this code tho
Factorise the value under the root and remove factors that are repeated 'degree' times, taking one of the factors outside.

Use code tabs.
Would you mind showing some code to explain that specific step? Thanks a lot
The code, indented and tagged.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <cmath>
using namespace std;

int main()
{
  int degree, a, b, z = 1;
  double root, y, x;

  cout << "Please enter the degree of the root: ";
  cin >> degree;
  while (degree < 2) {
    cout << "Please enter a degree greater than or equal to 2: ";
    cin >> degree;
  }

  cout << "Please enter the value under the root: ";
  cin >> x;
  while (x < 0) {
    cout << "Please enter a positve number as the value: ";
    cin >> x;
  }

  root = 1.0 / degree;
  y = pow(x, root);
  z = pow(y, degree);

  if (z == x) {
    cout << "The answer is " << y;
    return 0;
  }

  for (int i = x / 2; i > 0; i--) {
    a = pow(i, 1 / degree);
    if (pow(a, degree) == i) {
      cout << "The simplifed radical is " << a << " * degree " << degree << " root " << x / i;
      return 0;
    }
  }
}



$ g++ -Wall -Wextra -Wfloat-equal foo.cpp
foo.cpp: In function ‘int main()’:
foo.cpp:28:12: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
   28 |   if (z == x) {
      |            ^
foo.cpp:35:27: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
   35 |     if (pow(a, degree) == i) {
      |                           ^
foo.cpp:7:18: warning: unused variable ‘b’ [-Wunused-variable]
    7 |   int degree, a, b, z = 1;
      |                  ^

Floats are tricky things to compare properly. If you can make all the interesting parts work in integer arithmetic, so much the better.
http://c-faq.com/fp/fpequal.html

Also, your return at line 37 means the whole program ends at the first output. Is that right?
I think so yeah
@OP See: https://www.mathopenref.com/radical.html

For your problem it might be a lot simpler than you are making it. Do what @lastchance says

2^4 = 16 (16 is the radicand)

Keep dividing by 2 until the radicand isn't exceeded
(2*2*2) * 2 = 16
(2^3) * 2 = 16

Get the cube root of both sides :
cube_root( (2^3) * 2) = cube root (16)
So, cube_root(16) = 2 * cube_root(2)
Last edited on
For the given radicand:
check if n^degree is a factor of radicand, for successively n=2, 3, 5, 7, ...
If it is then take one factor of n outside and divide the radicand by n^degree before continuing.

- you can check for divisibility with the remainder operator (%)
- you may have to check multiple times for each n (e.g. 2^6 = (2^3)*(2^3));
- strictly you only have to consider prime n, but, unless you want to check for primality first, just do n=2 and then the odd numbers;
- you can't simplify more once n^degree > radicand;
- it's probably worth writing a routine ipow(n,exponent) to calculate integer powers; std::pow may lead you into floating-point finite-precision problems.


Please enter the degree of the root: 3
Please enter the value under the root: 4802000
The simplifed radical is 70 * degree 3 root 14

Last edited on
eep, don't brute force it.
work down like you would a prime factorization, keeping track of how many of each factor.
here, you want all the ones that appear 3+ times.

eg the above is 2*2*2*2 * 300125
which is 2^4 * 5^3 * 2401
2401 is *7 ^4
then rebuild your answer
2*2*2 * 5*5*5 *7*7*7 =
which, unsurprisingly, is 70 cubed (2*5*7 = 70)
etc. (also, channeling iago, more not surprise that 2*7 is left over = 14 = the root...)

they don't have to actually be primes. if you find that 10*10*10 is a factor, it works exactly the same way, but its actually more complicated because you can't find the same factors twice, (so if you find 3*3*3*3... many is a factor, finding that 9*9*9... is also a factor won't work by saying both 3 and 9 are in the rebuild equation... it won't work out).

its not an exercise on finding primes. Just stuff a big array list of all the primes or a bool lookup table or whatever in and keep going.
Last edited on
work down like you would a prime factorization

That's completely unnecessary
- work up, not down: you want to remove small-number factors as fast as possible to make the radicand small.


keeping track of how many of each factor

That's unnecessary; just remove each degree-length parcel of them as you work up.


if you find that 10*10*10 is a factor,

You won't. You will have dealt with 2 and 5 before that. There would never be any need to look at 10.
Thanks yall for helping! I'll try to work on it now
- work up, not down:

Direction is arbitrary :) I went 2,3,5,7 ... order as well. I called it working down because the target is getting smaller. You call it working up because the factor candidates are increasing.

That's unnecessary; just remove each degree-length parcel of them as you work up.

It is still tracking the information. Honestly value *= factor if the current factor has more than degree is fine, repeat that for multiples (like 7^30th can be repeated in the result). Agreed, you would not really keep it in a list of factor/count pairs (that was to see it on paper).

the third point, yes, that can't happen. Oops!

-- regardless of what you do, you may run into the factor problem. It could take a while to find nothing if the root of a large prime is offered.
Last edited on
One simple way. I make no claims re efficiency as it keeps a map of factor/count! As has been pointed out above, it can be done without this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <map>
#include <cmath>

int main() {
	unsigned num {};
	unsigned deg {};

	std::cout << "Enter number: ";
	std::cin >> num;

	std::cout << "Enter power degree: ";
	std::cin >> deg;

	if (deg < 2)
		return (std::cout << "powr degree must be at least 2\n"), 1;

	std::map<unsigned, unsigned> powrs;

	const auto ispwr {[&](unsigned rt) {
		while ((num % rt) == 0) {
			++powrs[rt];
			num /= rt;
		}}};

	ispwr(2);

	for (unsigned rt {3}, upper {(unsigned)std::sqrt(num)}; rt <= upper; rt += 2)
		ispwr(rt);

	unsigned rt {1};

	for (auto& p : powrs)
		while (p.second >= deg) {
			rt *= p.first;
			p.second -= deg;
		}

	unsigned tot {1};

	for (const auto& p : powrs)
		if (p.second > 0)
			for (unsigned pw {}; pw < p.second; ++pw)
				tot *= p.first;

	std::cout << "The simplified radical is ";

	if (rt > 1)
		std::cout << rt;

	if (tot > 1) {
		if (rt > 1)
			std::cout << " *";

		std::cout << " degree " << deg << " root " << tot;
	}

	std::cout << '\n';
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <cmath>
using namespace std;

int main(){
	int degree,a,b,y,num,z=1,n=2,ndeg=0;
	double root,times=1;
	cout << "Please enter the degree of the root: ";
	cin >> degree;
	while (degree<2){
		cout << "Please enter a degree greater than or equal to 2: ";
		cin >> degree;
	}
	cout << "Please enter the value under the root: ";
	cin >> num;
	while (num<0){
		cout << "Please enter a positve number as the value: ";
		cin >> num;
	}
	root=1.0/degree;
	y=pow(num,root);
	z=pow(y,degree);
	
	if (z==num){
		cout << "The answer is " << y;
		return 0;
	}
	
	while (ndeg<num){
		ndeg=pow(n,degree);
		if (num%ndeg==0){
			times=times*n;
			num=num/ndeg;
			n+=2;
		}
	}
	cout << "The simplified radical is " << times << " * degree " << degree << " root " << num;
	return 0;

	


}

I used the method suggested by you all and wrote this code. It still seems to have some problems though as it works for some numbers but not the others. For example it works fine when I typed in degree 3 root 8 but it didn't work out when I typed in degree 3 root 125. Does anyone know why this is happening and able to help me fix this problem? Thanks!
Last edited on
is n+= 2 possibly in an if that it should not be on 34?
where should I place the n+=2 then
outside the if, I think, so it increments every time? is this supposed to be 2,3,5,7, ... if so you need more, you need if its 2 add 1 else add 2.

also, unrelated, but +=, *=, etc are useful shortcut operators.
times *=n; is same as times = times*n;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <cmath>
using namespace std;

int main(){
	int degree,num,n=2,ndeg=0;
	double times=1;
	cout << "Please enter the degree of the root: ";
	cin >> degree;
	while (degree<2){
		cout << "Please enter a degree greater than or equal to 2: ";
		cin >> degree;
	}
	cout << "Please enter the value under the root: ";
	cin >> num;
	while (num<0){
		cout << "Please enter a positve number as the value: ";
		cin >> num;
	}

	
	while (ndeg<num){
		ndeg=pow(n,degree);
		if (num%ndeg==0){
			times=times*n;
			num=num/ndeg;
		}
		if (n%2==1){
		    n+=2;
		}
		else{
		    n++;
		}
	}
	if (num==1){
	    cout << "The answer is " << times;
	    return 0;
	}
	
	cout << "The simplified radical is " << times << " * degree " << degree << " root " << num;
	return 0;
}
	

I think I did it now! Everything works fine in the code for me. Please help me double check to make sure it is good. Thanks so much for the help along the way!!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <cmath>
using namespace std;

unsigned long long ipow( unsigned long long n, int exponent ) { return exponent ? n * ipow( n, exponent - 1 ) : 1; }

//======================================================================

void simplify( int degree, unsigned long long &radicand, unsigned long long &front )
{
   unsigned long long unfactored = radicand;          // to remove ALL previous factors, not just groups of degree
   for ( int n = 2; ; n += 1 + ( n > 2) )             // 2, 3, 5, 7, ... (or primes if pre-computed)
   {
      unsigned long long test = ipow( n, degree );
      while( true )                                   // deal with all factors n
      {
         if ( test > unfactored ) return;             // no other n^degree factors possible for this or higher n
         if ( unfactored % test )                     // strip less-than-degree factors to keep as small as possible
         {
            while ( unfactored % n == 0 ) unfactored /= n;
            break;
         }
         else
         {
            front      *= n;                          // shift n to front and remove n^degree inside
            radicand   /= test;
            unfactored /= test;
         }
      }
   }
}

//======================================================================

int main()
{
   int degree;
   unsigned long long radicand, front = 1;

   cout << "Please enter the degree of the root: ";   cin >> degree;
   cout << "Please enter the value under the root: ";   cin >> radicand;

   simplify( degree, radicand, front );
   cout << "The simplified radical is " << front << " * degree " << degree << " root " << radicand << '\n';
}

Pages: 12