import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	}

	//	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	}
	public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	}



} import java.io.IOException; IOException java.io import java.util.ArrayList; ArrayList java.util import java.util.Scanner; Scanner java.util public class Main {
	public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	}

	//	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	}
	public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	}



} Main public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	} main {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	} Scanner sc = new Scanner(System.in); sc new Scanner(System.in) int A = sc.nextInt(); A sc.nextInt() sc.nextInt sc int B = sc.nextInt(); B sc.nextInt() sc.nextInt sc int H = sc.nextInt(); H sc.nextInt() sc.nextInt sc int M = sc.nextInt(); M sc.nextInt() sc.nextInt sc double sec = (H*3600+H*60); sec (H*3600+H*60) H*3600 H 3600 H*60 H 60 double jikanKakudo = H*30+M*0.5; jikanKakudo H*30+M*0.5 H*30 H 30 M*0.5 M 0.5 double hunKakudo = M*6; hunKakudo M*6 M 6 double kakudo = Math.abs(hunKakudo- jikanKakudo); kakudo Math.abs(hunKakudo- jikanKakudo) Math.abs Math hunKakudo- jikanKakudo hunKakudo jikanKakudo double ans = 0; ans 0 if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		} kakudo == 0 kakudo 0 {
			ans = Math.abs(A-B);
		} ans = Math.abs(A-B) ans Math.abs(A-B) Math.abs Math A-B A B if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		} kakudo == 180 kakudo 180 {
			ans = A+B;
		} ans = A+B ans A+B A B if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		} kakudo>180 kakudo 180 {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		} kakudo = 360 - kakudo kakudo 360 - kakudo 360 kakudo ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo))) ans Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo))) Math.sqrt Math A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)) A*A + B*B A*A A A B*B B B 2*A*B*Math.cos(Math.toRadians(kakudo)) B 2*A*B*Math.cos(Math.toRadians(kakudo)) 2 A B Math.cos(Math.toRadians(kakudo)) Math.cos Math Math.toRadians(kakudo) Math.toRadians Math kakudo {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		} ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo))) ans Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo))) Math.sqrt Math A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)) A*A + B*B A*A A A B*B B B 2*A*B*Math.cos(Math.toRadians(kakudo)) B 2*A*B*Math.cos(Math.toRadians(kakudo)) 2 A B Math.cos(Math.toRadians(kakudo)) Math.cos Math Math.toRadians(kakudo) Math.toRadians Math kakudo System.out.println(ans) System.out.println System.out System System.out ans String[] args args //	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	} binarySearch {
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	} int lowerBorder = -1; lowerBorder -1 1 int upperBorder = orderedArray.length; upperBorder orderedArray.length orderedArray orderedArray.length int mid; mid while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		} upperBorder - lowerBorder >1 upperBorder - lowerBorder upperBorder lowerBorder 1 {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		} mid = (upperBorder + lowerBorder)/2 mid (upperBorder + lowerBorder)/2 (upperBorder + lowerBorder) upperBorder lowerBorder 2 if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			} orderedArray[mid]<=num orderedArray[mid] orderedArray mid num {
				lowerBorder = mid;
			} lowerBorder = mid lowerBorder mid {
				upperBorder = mid;
			} upperBorder = mid upperBorder mid return lowerBorder; lowerBorder long num num long[] orderedArray orderedArray //二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	} binarySearch {
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	} int lowerBorder = -1; lowerBorder -1 1 int upperBorder = orderedList.size(); upperBorder orderedList.size() orderedList.size orderedList int mid; mid while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		} upperBorder - lowerBorder >1 upperBorder - lowerBorder upperBorder lowerBorder 1 {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		} mid = (upperBorder + lowerBorder)/2 mid (upperBorder + lowerBorder)/2 (upperBorder + lowerBorder) upperBorder lowerBorder 2 if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			} orderedList.get(mid)<=num orderedList.get(mid) orderedList.get orderedList mid num {
				lowerBorder = mid;
			} lowerBorder = mid lowerBorder mid {
				upperBorder = mid;
			} upperBorder = mid upperBorder mid return lowerBorder; lowerBorder long num num ArrayList<Long> orderedList orderedList //aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	} gcd {
        return b == 0 ? a: gcd(b, a % b);
	} return b == 0 ? a: gcd(b, a % b); b == 0 ? a: gcd(b, a % b) b == 0 b 0 a gcd(b, a % b) gcd b a % b a b int a a int b b public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	} gcd {
        return b == 0 ? a: gcd(b, a % b);
	} return b == 0 ? a: gcd(b, a % b); b == 0 ? a: gcd(b, a % b) b == 0 b 0 a gcd(b, a % b) gcd b a % b a b long a a long b b public class Main {
	public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	}

	//	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	}
	public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	}



} public class Main {
	public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	}

	//	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	}
	public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	}



} Main
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) throws IOException {
//		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//		String W	 = in.readLine();
//		int num = Integer.parseInt(W.split(" ")[0]);

		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int H = sc.nextInt();
		int M = sc.nextInt();


		double sec = (H*3600+H*60);

		double jikanKakudo = H*30+M*0.5;
		double hunKakudo = M*6;
		double kakudo = Math.abs(hunKakudo- jikanKakudo);
		double ans = 0;

		if(kakudo == 0){
			ans = Math.abs(A-B);
		}else if(kakudo == 180){
			ans = A+B;
		}else if(kakudo>180) {
			kakudo = 360 - kakudo;
			ans = Math.sqrt(A*A + B*B - 2*A*B*Math.cos(Math.toRadians(kakudo)));
		}else {

			ans = Math.sqrt(A*A + B*B -2*A*B*Math.cos(Math.toRadians(kakudo)));
		}

			System.out.println(ans);

	}

	//	//二分探索
	//k <= num となる最小の配列要素kのインデックスを返す
	static private int binarySearch(long num, long[] orderedArray){
		int lowerBorder = -1;
		int upperBorder = orderedArray.length;
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedArray[mid]<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//二分探索
	//k <= num となる最小のList要素kのインデックスを返す
	static private int binarySearch(long num, ArrayList<Long> orderedList){
		int lowerBorder = -1;
		int upperBorder = orderedList.size();
		int mid;

		while(upperBorder - lowerBorder >1) {
			mid = (upperBorder + lowerBorder)/2;
			if(orderedList.get(mid)<=num) {
				lowerBorder = mid;
			}else {
				upperBorder = mid;
			}
		}
		return lowerBorder;
	}

	//aとbの最小公倍数を求める
	public static int gcd(int a, int b) {
        return b == 0 ? a: gcd(b, a % b);
	}
	public static long gcd(long a, long b) {
        return b == 0 ? a: gcd(b, a % b);
	}



}
