提问人:Wouter 提问时间:10/16/2023 最后编辑:Guru StronWouter 更新时间:10/31/2023 访问量:1937
如何将 INumber<T> 与 int 相乘?[复制]
How can I multiply a INumber<T> with an int? [duplicate]
问:
我应该如何在最后一行实现 int() 乘法?z * 2
public static TResult Test<TResult>() where TResult : INumber<TResult>
{
TResult x = TResult.AdditiveIdentity;
TResult y = TResult.MultiplicativeIdentity;
TResult z = x * y;
TResult z2 = z * 2; // <--- this gives the CS0019 error "The operator * cannot be applied to operands of type 'TResult' and 'int'
return z2;
}
---建议的解决方案是添加一个接口,但它破坏了这一点:IMultiplyOperators<TResult, int, TResult>
public static void Tester()
{
Test<decimal>(); // CS0315 Tye type decimal cannot be used as type parameter TResult..... there is no boxing conversion
}
现在,我将自己注入函数并使用:
public static TResult Test<TResult>(Func<TResult, int, TResult> mul) where TResult : INumber<TResult>
{
TResult x = TResult.AdditiveIdentity;
TResult y = TResult.MultiplicativeIdentity;
TResult z = x * y;
TResult z2 = mul(z, 2);
return z2;
}
答:
16赞
ProgrammingLlama
10/16/2023
#1
您需要添加接口:IMultiplyOperators<, ,>
public static TResult Test<TResult>() where TResult : INumber<TResult>, IMultiplyOperators<TResult, int, TResult>
{
TResult x = TResult.AdditiveIdentity;
TResult y = TResult.MultiplicativeIdentity;
TResult z = x * y;
TResult z2 = z * 2;
return z2;
}
您可以在此处查看操作员界面列表。
评论
0赞
Wouter
10/16/2023
Althoug 这确实有效。看看十进制.cs,它不仅实现了接口IMultiplyOperators<TResult, int, TResult>
IMultiplyOperators<decimal,decimal,decimal>
0赞
ProgrammingLlama
10/16/2023
@Wouter恐怕我实际上并不知道在这种情况下十进制的解决方案。一个适用于乘以 2 的简单解决方案只是增加自身,但这绝对不会扩展。另一种方法可能是将整数 2 转换为使用 ,但我有点觉得这稍微违背了通用数学的意义,所以我不确定。z
TResult
Convert.ChangeType
0赞
Wouter
10/16/2023
事实上,2 只是一个例子(可以添加 Z + Z)。也许有一个接口可以进行(隐式)转换?
0赞
Wouter
10/16/2023
注入到此函数将起作用。Func<TResult, int, TResult> multiply
25赞
Dmitry Bychenko
10/16/2023
#2
我建议转换为然后再乘:2
TResult
TResult z2 = z * TResult.CreateChecked(2);
在这里,我们从整数值创建实例,同时检查溢出和类似的可能错误(如果无法转换为:either 或 ),将抛出异常。TResult
2
2
2
TResult
OverflowException
NotSupportedException
法典:
public static TResult Test<TResult>() where TResult : INumber<TResult>
{
TResult x = TResult.AdditiveIdentity;
TResult y = TResult.MultiplicativeIdentity;
TResult z = x * y;
TResult z2 = z * TResult.CreateChecked(2);
return z2;
}
演示:
Console.WriteLine(Test<decimal>());
输出:
0
评论
0赞
Wouter
10/17/2023
我徘徊着是否可以有一个支持隐式转换器 int 到 TResult 的接口。
1赞
Damien_The_Unbeliever
10/18/2023
@Wouter - 隐式转换应始终是安全的。你怎么对你的信念/断言如此有信心,这些信念/断言总是可以转换为任何将执行数学的领域,以便应该存在隐式转换而不是显式转换?2
0赞
Wouter
10/18/2023
我的意思是,就像添加一个接口一样,如果十进制实现它,转换就不需要“CreateCheck”,它只是一个大开关,并不是真正的多态/类型安全。IImplicitConvert<int, TResult>
6赞
Olivier Jacot-Descombes
10/17/2023
#3
虽然不是通用解决方案,但在这种情况下(乘数 = 2),您可以简单地写成:
TResult z2 = z + z;
除了 z 是 TResult.AdditiveIdentity * TResult.MultiplicativeIdentity。但 TResult.AdditiveIdentity 为零。所以结果将为零。
评论
6赞
Ilmari Karonen
10/17/2023
更一般地说,任何整数的乘法都可以在数学上定义(如果需要,也可以实现)重复加法(可能是否定)。在实践中,您需要实现类似农民乘法算法的东西,该算法可以仅使用 O(log n) 加法(以及一些整数位操作)将数字乘以整数 n。当然,这样做的结果可能与“原生”整数乘法的行为相匹配,也可能不匹配,尽管对于相当理智的数字类型来说,它确实应该。
0赞
Wouter
10/18/2023
这是一个最小的例子,它表明乘法正在 TResult 上工作。接下来,将其乘以浮点数/双倍数怎么样。甚至是另一个 INumber?public static void Test<X, Y>(X x, Y y) where X : INumber<X> where Y : INumber<Y> => Console.WriteLine(x * y);
评论