ackb ঠিক আছে যে এই ভেক্টর ভিত্তিক সমাধানগুলিকে সঠিক গড় হিসাবে বিবেচনা করা যায় না, এগুলি কেবলমাত্র ইউনিট ভেক্টর অংশগুলির মধ্যে একটি গড়। তবে, এসিবিবির প্রস্তাবিত সমাধান গাণিতিকভাবে শোনায় না।
নিম্নলিখিতটি একটি সমাধান যা গাণিতিকভাবে কমানোর লক্ষ্য থেকে উদ্ভূত হয়েছে (কোণ [i] - গড় অ্যাংগল) ^ 2 (যেখানে প্রয়োজনে পার্থক্যটি সংশোধন করা হয়েছে), এটি এটিকে কোণগুলির সত্যিকারের গাণিতিক গড় করে তোলে।
প্রথমত, আমাদের কোণ সংখ্যাগুলির মধ্যে পার্থক্যটি তাদের সাধারণ সংখ্যা সমকক্ষগুলির মধ্যে পার্থক্যের তুলনায় ঠিক কী ক্ষেত্রে ঠিক তা দেখতে হবে। X এবং y কোণগুলি বিবেচনা করুন, যদি y> = x - 180 এবং y <= x + 180 হয় তবে আমরা পার্থক্যটি (xy) সরাসরি ব্যবহার করতে পারি। অন্যথায়, যদি প্রথম শর্তটি পূরণ না হয় তবে আমাদের অবশ্যই y এর পরিবর্তে গণনায় (y + 360) ব্যবহার করতে হবে। অনুরূপ, দ্বিতীয় শর্তটি যদি পূরণ না হয় তবে আমাদের অবশ্যই y এর পরিবর্তে (y-360) ব্যবহার করতে হবে। যেহেতু কার্ভের সমীকরণটি আমরা কেবলমাত্র সেই পয়েন্টগুলিতে পরিবর্তনগুলি হ্রাস করছি যেখানে এই অসমতাগুলি সত্য থেকে মিথ্যা বা বিপরীতে পরিবর্তিত হয়, তাই আমরা এই পয়েন্টগুলি দ্বারা পৃথক করে পুরো [0,360) পরিসরকে বিভাগগুলির একটি সেটে আলাদা করতে পারি। তারপরে, আমাদের কেবলমাত্র এই বিভাগগুলির প্রত্যেকের ন্যূনতম এবং তারপরে প্রতিটি বিভাগের ন্যূনতম, যা গড়, তা খুঁজে বের করতে হবে।
এখানে একটি চিত্র প্রদর্শিত হচ্ছে যেখানে কোণগুলির পার্থক্য গণনা করতে সমস্যা দেখা দেয়। যদি x ধূসর জায়গায় থাকে তবে সমস্যা হবে।
একটি পরিবর্তনক কমানোর জন্য, বক্ররেখার উপর নির্ভর করে আমরা কী কম করতে চাই তার ডেরিভেটিভ নিতে পারি এবং তারপরে আমরা টার্নিং পয়েন্টটি পাই (যেখানে এটি ডেরিভেটিভ = 0)।
এখানে আমরা সাধারণ পাটিগণিত গড় সূত্রটি সংগ্রহ করতে বর্গক্ষেত্রের পার্থক্য হ্রাস করার ধারণাটি প্রয়োগ করব: যোগফল (একটি [i]) / এন। বক্ররেখ y = যোগফল ((a [i] -x) ^ 2) এইভাবে হ্রাস করা যেতে পারে:
y = sum((a[i]-x)^2)
= sum(a[i]^2 - 2*a[i]*x + x^2)
= sum(a[i]^2) - 2*x*sum(a[i]) + n*x^2
dy\dx = -2*sum(a[i]) + 2*n*x
for dy/dx = 0:
-2*sum(a[i]) + 2*n*x = 0
-> n*x = sum(a[i])
-> x = sum(a[i])/n
আমাদের সমন্বিত পার্থক্য সহ এটি এখন কার্ভে প্রয়োগ করুন:
খ = যেখানে একটি (কৌণিক) পার্থক্য একটি [i] -xc = উপসেট যেখানে একটি (কৌণিক) পার্থক্য (একটি [i] -360) -x সিএন = সিডি এর আকার = একটি উপসেট যেখানে সঠিক (কৌণিক) পার্থক্য (a [i] +360) -x dn = d এর আকার
y = sum((b[i]-x)^2) + sum(((c[i]-360)-b)^2) + sum(((d[i]+360)-c)^2)
= sum(b[i]^2 - 2*b[i]*x + x^2)
+ sum((c[i]-360)^2 - 2*(c[i]-360)*x + x^2)
+ sum((d[i]+360)^2 - 2*(d[i]+360)*x + x^2)
= sum(b[i]^2) - 2*x*sum(b[i])
+ sum((c[i]-360)^2) - 2*x*(sum(c[i]) - 360*cn)
+ sum((d[i]+360)^2) - 2*x*(sum(d[i]) + 360*dn)
+ n*x^2
= sum(b[i]^2) + sum((c[i]-360)^2) + sum((d[i]+360)^2)
- 2*x*(sum(b[i]) + sum(c[i]) + sum(d[i]))
- 2*x*(360*dn - 360*cn)
+ n*x^2
= sum(b[i]^2) + sum((c[i]-360)^2) + sum((d[i]+360)^2)
- 2*x*sum(x[i])
- 2*x*360*(dn - cn)
+ n*x^2
dy/dx = 2*n*x - 2*sum(x[i]) - 2*360*(dn - cn)
for dy/dx = 0:
2*n*x - 2*sum(x[i]) - 2*360*(dn - cn) = 0
n*x = sum(x[i]) + 360*(dn - cn)
x = (sum(x[i]) + 360*(dn - cn))/n
এটি এককভাবে ন্যূনতম প্রাপ্তির পক্ষে যথেষ্ট নয়, যখন এটি সাধারণ মানের জন্য কাজ করে, এতে একটি সীমাহীন সেট রয়েছে, সুতরাং ফলাফলটি অবশ্যই সেটটির সীমার মধ্যেই থাকবে এবং তাই বৈধ। আমাদের একটি পরিসরের মধ্যে ন্যূনতম প্রয়োজন (বিভাগটি দ্বারা সংজ্ঞায়িত)। যদি ন্যূনতমটি আমাদের বিভাগের নিম্ন সীমাটির চেয়ে কম হয় তবে সেগমেন্টের সর্বনিম্নটি অবশ্যই নিম্ন সীমানায় থাকতে হবে (কারণ চতুর্ভুজ বক্ররেখাগুলির কেবলমাত্র 1 টি টার্নিং পয়েন্ট রয়েছে) এবং যদি ন্যূনতমটি আমাদের বিভাগের উপরের সীমানার চেয়ে বেশি হয় তবে বিভাগটির সর্বনিম্ন হয় ঊর্ধ্বসীমা. আমাদের প্রতিটি বিভাগের জন্য সর্বনিম্ন থাকার পরে, আমরা কেবলমাত্র যা হ্রাস করছি তার জন্য সর্বনিম্ন মানটি আমরা খুঁজে পাই (যোগফল ((খ [i] -x) ^ 2) + সমষ্টি ((সি [আমি] -360 ) -বি) ^ 2) + সমষ্টি (((ডি [আমি] +360) -সি) ^ 2))।
এখানে বক্ররেখাতে একটি চিত্র রয়েছে যা এটি দেখায় যে এটি কীভাবে পয়েন্টে পরিবর্তিত হয় যেখানে x = (a [i] +180)% 360। ডেটা সেটটি প্রশ্নযুক্ত {65,92,230,320,250}}
এখানে জাভাতে অ্যালগরিদমের একটি বাস্তবায়ন রয়েছে, যার মধ্যে কয়েকটি অপটিমাইজেশন রয়েছে, এর জটিলতা হ'ল O (nlogn)। যদি আপনি তুলনা ভিত্তিক সাজানটিকে কোনও তুলনামূলক ভিত্তিক সাজানো, যেমন র্যাডিক্স সাজানোর সাথে প্রতিস্থাপন করেন তবে এটি ও (এন) এ হ্রাস করা যাবে।
static double varnc(double _mean, int _n, double _sumX, double _sumSqrX)
{
return _mean*(_n*_mean - 2*_sumX) + _sumSqrX;
}
//with lower correction
static double varlc(double _mean, int _n, double _sumX, double _sumSqrX, int _nc, double _sumC)
{
return _mean*(_n*_mean - 2*_sumX) + _sumSqrX
+ 2*360*_sumC + _nc*(-2*360*_mean + 360*360);
}
//with upper correction
static double varuc(double _mean, int _n, double _sumX, double _sumSqrX, int _nc, double _sumC)
{
return _mean*(_n*_mean - 2*_sumX) + _sumSqrX
- 2*360*_sumC + _nc*(2*360*_mean + 360*360);
}
static double[] averageAngles(double[] _angles)
{
double sumAngles;
double sumSqrAngles;
double[] lowerAngles;
double[] upperAngles;
{
List<Double> lowerAngles_ = new LinkedList<Double>();
List<Double> upperAngles_ = new LinkedList<Double>();
sumAngles = 0;
sumSqrAngles = 0;
for(double angle : _angles)
{
sumAngles += angle;
sumSqrAngles += angle*angle;
if(angle < 180)
lowerAngles_.add(angle);
else if(angle > 180)
upperAngles_.add(angle);
}
Collections.sort(lowerAngles_);
Collections.sort(upperAngles_,Collections.reverseOrder());
lowerAngles = new double[lowerAngles_.size()];
Iterator<Double> lowerAnglesIter = lowerAngles_.iterator();
for(int i = 0; i < lowerAngles_.size(); i++)
lowerAngles[i] = lowerAnglesIter.next();
upperAngles = new double[upperAngles_.size()];
Iterator<Double> upperAnglesIter = upperAngles_.iterator();
for(int i = 0; i < upperAngles_.size(); i++)
upperAngles[i] = upperAnglesIter.next();
}
List<Double> averageAngles = new LinkedList<Double>();
averageAngles.add(180d);
double variance = varnc(180,_angles.length,sumAngles,sumSqrAngles);
double lowerBound = 180;
double sumLC = 0;
for(int i = 0; i < lowerAngles.length; i++)
{
//get average for a segment based on minimum
double testAverageAngle = (sumAngles + 360*i)/_angles.length;
//minimum is outside segment range (therefore not directly relevant)
//since it is greater than lowerAngles[i], the minimum for the segment
//must lie on the boundary lowerAngles[i]
if(testAverageAngle > lowerAngles[i]+180)
testAverageAngle = lowerAngles[i];
if(testAverageAngle > lowerBound)
{
double testVariance = varlc(testAverageAngle,_angles.length,sumAngles,sumSqrAngles,i,sumLC);
if(testVariance < variance)
{
averageAngles.clear();
averageAngles.add(testAverageAngle);
variance = testVariance;
}
else if(testVariance == variance)
averageAngles.add(testAverageAngle);
}
lowerBound = lowerAngles[i];
sumLC += lowerAngles[i];
}
//Test last segment
{
//get average for a segment based on minimum
double testAverageAngle = (sumAngles + 360*lowerAngles.length)/_angles.length;
//minimum is inside segment range
//we will test average 0 (360) later
if(testAverageAngle < 360 && testAverageAngle > lowerBound)
{
double testVariance = varlc(testAverageAngle,_angles.length,sumAngles,sumSqrAngles,lowerAngles.length,sumLC);
if(testVariance < variance)
{
averageAngles.clear();
averageAngles.add(testAverageAngle);
variance = testVariance;
}
else if(testVariance == variance)
averageAngles.add(testAverageAngle);
}
}
double upperBound = 180;
double sumUC = 0;
for(int i = 0; i < upperAngles.length; i++)
{
//get average for a segment based on minimum
double testAverageAngle = (sumAngles - 360*i)/_angles.length;
//minimum is outside segment range (therefore not directly relevant)
//since it is greater than lowerAngles[i], the minimum for the segment
//must lie on the boundary lowerAngles[i]
if(testAverageAngle < upperAngles[i]-180)
testAverageAngle = upperAngles[i];
if(testAverageAngle < upperBound)
{
double testVariance = varuc(testAverageAngle,_angles.length,sumAngles,sumSqrAngles,i,sumUC);
if(testVariance < variance)
{
averageAngles.clear();
averageAngles.add(testAverageAngle);
variance = testVariance;
}
else if(testVariance == variance)
averageAngles.add(testAverageAngle);
}
upperBound = upperAngles[i];
sumUC += upperBound;
}
//Test last segment
{
//get average for a segment based on minimum
double testAverageAngle = (sumAngles - 360*upperAngles.length)/_angles.length;
//minimum is inside segment range
//we test average 0 (360) now
if(testAverageAngle < 0)
testAverageAngle = 0;
if(testAverageAngle < upperBound)
{
double testVariance = varuc(testAverageAngle,_angles.length,sumAngles,sumSqrAngles,upperAngles.length,sumUC);
if(testVariance < variance)
{
averageAngles.clear();
averageAngles.add(testAverageAngle);
variance = testVariance;
}
else if(testVariance == variance)
averageAngles.add(testAverageAngle);
}
}
double[] averageAngles_ = new double[averageAngles.size()];
Iterator<Double> averageAnglesIter = averageAngles.iterator();
for(int i = 0; i < averageAngles_.length; i++)
averageAngles_[i] = averageAnglesIter.next();
return averageAngles_;
}
কোণগুলির একটি সেটের গাণিতিক গড়টি গড়টি কী হওয়া উচিত তা সম্পর্কে আপনার স্বজ্ঞাত ধারণার সাথে একমত হতে পারে না। উদাহরণস্বরূপ, সেটটির গাণিতিক গড়টি {179,179,0,181,181} 216 (এবং 144)। আপনি অবিলম্বে উত্তরটি 180 এর মতো বলে মনে করছেন, তবে এটি সুপরিচিত যে পাটিগণিত গড়টি প্রান্তিক মানগুলি দ্বারা খুব বেশি প্রভাবিত। আপনার এও মনে রাখা উচিত যে কোণগুলি কোনও ভেক্টর নয়, যেমনটি কখনও কখনও কোণগুলির সাথে আচরণ করার সময় মনে হয়।
এই অ্যালগরিদম অবশ্যই সমস্ত পরিমাণে প্রযোজ্য যা মডিউলার গাণিতিক (ন্যূনতম সামঞ্জস্য সহ) মান্য করে যেমন দিনের সময় হিসাবে।
আমি জোর দিয়ে বলতে চাই যে এটি ভেক্টর সমাধানগুলির বিপরীতে, যদিও এটি কোণগুলির একটি সত্য গড়, তবে এটির অবশ্যই প্রয়োজন হয় না যে এটি আপনার ব্যবহার করা উচিত সমাধান, সংশ্লিষ্ট ইউনিট ভেক্টরগুলির গড় ভাল হতে পারে আপনি প্রকৃতপক্ষে মূল্য ব্যবহার করা উচিত।