کبیسه گیری دقیق شمسی (آموزش)
سلام
تویه انجمن ios یه آموزشی دیدم در خصوص کبیسه گیری شمسی ( لینک) چون تویه انجمن ios عضو ویژه نیستم نتونستم اشتباهشون رو بهشون بگم و چون تویه همین انجمن هم سوالات زیادی در این مورد پرسیده شده بود گفتم بد نیست بیام اینجا این آموزش رو بزارم . خوب بریم سر اصل مطلب
تویه بیشتر کدهای که من دیدم برای کبیسه گیری شمسی اومدن گفتن سال کبیسه در تاریخ جلالی ( شمسی ) هر 4 سال یکبار اتقاق می افتد با این تفاوت که بعد از گذراندن هر 8 دوره ی 4 ساله ( 32 سال ) به جای 4 سال ، 5 سال محاسبه می شود. این تنها بخشی از قضیه هستش ! اصل مطلب از ویکی پدیا :
تقویم رسمی کنونی ایران معمولاً هر چهار سال یکبار کبیسه میشود و برای جبران کسر سال حقیقی، در آغاز هر دورهٔ ۲۹، ۳۳ یا ۳۷ساله، یک کبیسه پنج ساله وجود دارد. در یک فراز پنجهزارساله، مابهازای هر دورهٔ ۳۷ساله، نزدیک به پنج دورهٔ ۲۹ساله و تقریباً ۲۰ دورهٔ ۳۳ساله وجود دارد. ویکی پدیا
یه راه ساده برای این که بفهمیم کد های که در مورد کبیسه گیری نوشته شدن درست هستن یا نه ، این هست که ما بیایم این سال های رو که در پایین گفتم داخل کد امتحان کنیم اگه کبیسه بودن کد درسته ، اگه نبودن کد غلطه . 1304 و 1308 و 1341 و..
برای فهمیدن کبیسه های شمسی بر خلاف کبیسه های میلادی هیچ فرمول خاصی برای دستیابی به کبیسه های کل تاریخ نیست ! اگه هم باشه یه معادلات خیلی خیلی پیچیده هستش ! از اونجایی که ما کبیسه کل تاریخ رو نمیخوایم پس از سال 1 شمسی تا 1502 شمسی برامون کفایت میکنه .
اینم از کدش :
final int[] kabise = new int[]{ 4, 37, 66, 99, 132, 165, 198, 231, 264, 297, 326 , 359, 392, 425, 458, 491, 524, 553, 586, 619, 656, 685, 718, 751, 784, 817 , 850, 883, 916, 949, 978, 1011, 1044, 1077, 1110, 1143, 1176, 1209, 1238 , 1275, 1308, 1343, 1370, 1401, 1436, 1473, 1502 };
public boolean kabiseShamsi(int sal) { int k = 0; for (int i = 0; i <= sal; i += 4) { if (i > kabise[k]) { i++; k++; } if (sal == i) { return true; } } return false; }
اگه جای از کد رو متوجه نشدید یا اگه کد غلطه و کد بهتری دارید ممنون میشم اطلاع بدید.
با تشکر از همتون که وقت گذاشتید این مطلب رو خوندید.
سلام FSR . کد شما رو امتحان کردم خیلی عالی بود . اگر اشتباه نکنم یک باگ خیلی کوچکی هم داشت و در زمانی این باگ ظاهر میشد که به آخرین بازه تعیین شده در آرایه می رسیدیم ، دقیقاً یادم نیست ولی در کل الگوریتم خوبی بود .
من الگوریتم زیر را با توجه به این لینک پیاده سازی کردم . لطفا تست بفرمایید . ( این الگوریتم را به زودی برای دانش پذیران IOS قرار خواهم داد . )
public static void LeapYearSolar (int year) { BigDecimal constantNumber = new BigDecimal("0.24219858156"); double leapYearSolar = (year + 2346) * (0.24219859156); String strLeapYearSolar = Double.toString(leapYearSolar); BigDecimal bd = new BigDecimal(strLeapYearSolar); Integer intPart = bd.intValue(); BigDecimal bdInt = new BigDecimal(intPart); BigDecimal bdDec = bd.subtract(bdInt); //Compare ConstantNumber with bdDec int res = constantNumber.compareTo(bdDec); if ( res == 1 ) Log.i("Test" , " is Leap year solar " ); else if ( res == -1 ) Log.i("Test" , " is not Leap year solar "); }
فراخوانی Mehod نوشته شده :
LeapYearSolar(1395);
در ضمن با اجازه شما الگوریتمی که نوشته اید را در انجمن IOS قرار خواهم داد ، در صورت تمایل پیام خصوصی داده تا در انجمن IOS الگوریتم شما را قرار دهم .
دقیقا تویه کدوم سال باگ داره ؟
من از سال 1280 تا 1500 امتحان کردم باگی نداشت .
سلام دوستان این تابع هم همین کارو انجام میده . ببینین باگ داره یا نه، اگه به دردتون خورد استفاده کنید. البته این تابع هم مثل بقیه توابع در بازه ی خاصی کار می کنه و درست تشخیص میده.
public static boolean isLeapYear (int year){ double a = 0.025; int b = 266; double leapDays0; double leapDays1; if (year > 0) { leapDays0 = ((year + 38) % 2820) * 0.24219 + a; leapDays1 = ((year + 39) % 2820) * 0.24219 + a; }else if ((year < 0)){ leapDays0 = ((year + 39) % 2820) * 0.24219 + a; leapDays1 = ((year + 40) % 2820) * 0.24219 + a; }else { return false; } long frac0 = (int)((leapDays0 - (int)(leapDays0))*1000); long frac1 = (int)((leapDays1 - (int)(leapDays1))*1000); if (frac0 <= b && frac1 > b) { return true; }else{ return false; } }
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .