#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <functional>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits>

using namespace std;

#define ll long long

#define in(x) cin >> x
#define out(x) cout << x << endl

#define PI acos(-1)
#define pp push_back

#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl

#define vec2(type) vector<vector<type>>
#define vec3(type) vector<vector<vector<type>>>

#define For(i, n) for(int i = 0; i < n; i++)

#define inRange(x, a, b) (a <= x && x <= b)
#define between(x, a, b) (a < x && x < b)

template<typename T> void swap(T &a, T &b){
	T temp = a;
	a = b;
	b = temp;
}

template<typename T> void input(T *data, int n){
	For(i, n){
		cin >> data[i];
	}
}

template<typename T> void input(vector<T> &vec, int n){
	T temp;
	For(i, n){
		cin >> temp;
		vec.push_back(temp);
	}
}

template<typename T> void sort(vector<T> &ary){
	sort(ary.begin(), ary.end());
}

template<typename T> void rsort(vector<T> &ary){
	sort(ary.rbegin(), ary.rend());
}

void rstring(string &str){
	string temp = str;

	For(i, (int)str.size()){
		str[i] = temp[(str.size() - 1) - i];
	}
}

struct Vec{
	int x, y;
	Vec():
	x(0), y(0){}
	Vec(int _x, int _y):
	x(_x), y(_y){}
};

template<typename T> void print(T *x, int n){
	For(i, n){
		cout << x[i] << " ";
	}
	cout << endl;
}

template<typename T> void print(vector<T> &x){
	For(i, (int)x.size()){
		cout << x[i] << " ";
	}
	cout << endl;
}

int gcd(int n, int m){
	if(n % m == 0){
		return m;
	}
	else{
		return gcd(m, n % m);
	}
}

template<typename T> T binarySearch(vector<T> a, T target){
	int cur = (int)a.size() / 2;
	int upper = (int)a.size() - 1;
	int buttom = 0;
	while(1){
		if(a[cur] == target){
			return a[cur];
		}
		else if(a[cur] > target){
			upper = cur;
			cur = (buttom + cur) / 2;
		}
		else{
			buttom = cur;
			cur = (cur + upper) / 2;
		}
	}
}

template<typename T> T binarySearch(vector<T> a, T func(T), T target){
	int cur = (int)a.size() / 2;
	int upper = (int)a.size() - 1;
	int buttom = 0;
	while(1){
		int value = func(a[cur]);
		if(value == target){
			return a[cur];
		}
		else if(value > target){
			upper = cur;
			cur = (buttom + cur) / 2;
		}
		else{
			buttom = cur;
			cur = (cur + upper) / 2;
		}
	}
}

template<typename T>
class UnionFind{
public:
	vector<set<T>> unit_unit;
	int getUnionNumber(T elm){
		for(int i = 0; i < (int)unit_unit.size(); i++){
			int number = unit_unit[i].find();
			if(number !=unit_unit[i].end()){
				return i;
			}
		}
		return -1;
	}

	void mergeUnion(int baseUnitNum, int absorvedUnitNum){

	}
};

int func(int n, int k){

	int x = 1;
	while(1){
		if(n * x >= k){
			break;
		}
		x *= 2;
	}
	return x;
}

int main(){

	int n, k;
	cin >> n >> k;

	vector<int> bunbo;

	For(i, n){
		bunbo.push_back(func(i + 1, k));
	}
	int max_bunbo = bunbo[0];
	for(int i = 1; i < n; i++){
		if(bunbo[i] > max_bunbo){
			max_bunbo = bunbo[i];
		}
	}

	int bunshi = 0;
	For(i, n){
		bunshi += func(bunbo[i], max_bunbo);
	}

	printf("%.10f\n", (double)bunshi / max_bunbo / n);

	return 0;

}

Measured memory_bytes: 892