1- using System . Globalization ;
1+ using System . Globalization ;
22using System . Numerics ;
33using System . Reflection ;
44using Rationals ;
@@ -37,6 +37,33 @@ internal static Exception Fail(string msg = "")
3737 internal static int TokenType ( string str ) => _simaiLexerMap [ str ] ;
3838
3939 internal static bool IsModifier ( int tokenType ) => tokenType is L . MODIFIER or L . TAP_TO_STAR or L . STAR_TO_TAP or L . NO_STAR ;
40+
41+ public static ( int , int ) BarAndTick ( Rational time , int resolution , int extraTicks = 0 )
42+ {
43+ var bar = time . WholePart ;
44+ var tick = ( time . FractionPart * resolution ) . Round ( ) ;
45+ tick += extraTicks ;
46+
47+ while ( tick >= resolution )
48+ {
49+ tick -= resolution ;
50+ bar ++ ;
51+ }
52+ while ( tick < 0 )
53+ {
54+ tick += resolution ;
55+ bar -- ;
56+ }
57+
58+ return ( ( int ) bar , ( int ) tick ) ;
59+ }
60+
61+ public static int Tick ( Rational time , int resolution , int extraTicks = 0 , int ? min = null )
62+ {
63+ var r = ( int ) ( ( time * resolution ) . Round ( ) + extraTicks ) ;
64+ if ( min != null && r < min ) r = min . Value ;
65+ return r ;
66+ }
4067}
4168
4269internal static class ExtensionUtils
@@ -63,6 +90,17 @@ public static Rational Ceil(this Rational r)
6390 return r . WholePart + ( r . FractionPart == 0 ? 0 : 1 ) ;
6491 }
6592
93+ private static readonly Rational _half = new ( 1 , 2 ) ;
94+ // 工作范围仅限非负数;舍入策略方面,使用与系统库Math.Round相同的“四舍六入五成双”算法。
95+ public static BigInteger Round ( this Rational r )
96+ {
97+ if ( r < 0 ) throw new ArgumentOutOfRangeException ( nameof ( r ) ) ;
98+ var whole = r . WholePart ;
99+ var frac = r . FractionPart ;
100+ var shouldAdd = frac > _half || ( frac == _half && whole % 2 == 1 ) ;
101+ return whole + ( shouldAdd ? 1 : 0 ) ;
102+ }
103+
66104 public static Rational Sum ( this IEnumerable < Rational > source )
67105 {
68106 return source . Aggregate ( Rational . Zero , ( acc , r ) => acc + r ) ;
0 commit comments