C# 你能发现我的标记助手方法中的数学错误吗?
我已经制作了一个标记帮助器,用于渲染0到5颗星的星级,包括半颗星 这是标记,呈现五颗星:C# 你能发现我的标记助手方法中的数学错误吗?,c#,math,C#,Math,我已经制作了一个标记帮助器,用于渲染0到5颗星的星级,包括半颗星 这是标记,呈现五颗星: <star-rating rating="10"></star-rating> 但是我的方法有一个我找不到的数学错误。该方法生成以下输出(()=一颗星,(=半颗星): 这里有一个明显的模式,原因是什么 更新 我找到了一个丑陋的解决办法: double dec = stars - Math.Truncate(stars); if (dec == 0.5) { for (int
<star-rating rating="10"></star-rating>
但是我的方法有一个我找不到的数学错误。该方法生成以下输出(()
=一颗星,(
=半颗星):
这里有一个明显的模式,原因是什么
更新
我找到了一个丑陋的解决办法:
double dec = stars - Math.Truncate(stars);
if (dec == 0.5)
{
for (int s = 1; s < stars; s++)
{
sb.AppendFormat("<span class='fas fa-star text-warning text-outline'></span>");
}
sb.AppendFormat("<span class='fas fa-star-half'></span>");
}
else
{
for (int s = 0; s < stars; s++)
{
sb.AppendFormat("<span class='fas fa-star'></span>");
}
}
double dec=stars-数学截断(stars);
如果(dec==0.5)
{
对于(int s=1;s
如果有一个半星,它运行一个for循环,如果没有,它运行另一个for循环,违反了干燥原则…在for循环中,你将上升到
s
这意味着0.5
它将创建一个全星,因为它大于0
。你可以忽略Floor
这个stars
小数点,例如数学下限(1.5)=1
,这是一个可能的修正,见下文
for (int s = 0; s < Math.Floor(stars); s++)
{
sb.AppendFormat("<span class='fas fa-star'></span>");
}
for(int s=0;s
编辑:
Math.Truncate()
也可以。首先,我建议在此处使用十进制
类型,而不是双精度
,因为使用双精度
进行数学运算(然后对结果进行比较)时,可能会出现舍入错误。您会得到“幸运”在您的案例中,因为您使用的是<代码> 5 ,它似乎不存在这个问题,但是,例如,考虑您的代码行:
double dec = stars - Math.Truncate(stars);
如果stars
是2.4
,那么dec
将是0.3999999991
如果stars
是2.6
,那么dec
将是0.6000000000000009
如果您随后进行比较,则这两种情况都不会给出预期的输出:if(dec==0.4)
或if(dec==0.6)
。因此,一般来说,如果您要对数字进行数学运算并对结果进行比较,使用decimal
是一个好习惯
要解决问题中的问题,您可以使用以下几个技巧:
将decimal
转换为int
以获得整数部分
(int)2.5M==2
使用带1的模运算符(返回一个数除以另一个数的余数)获取小数部分
250万%1==0.5
例如:
// Loop from .5 to 10 in increments of .5 (the 'M' signifies that the number is a decimal)
for (decimal i = .5M; i <= 5; i += .5M)
{
Console.Write($"{i:0.0}: ");
// First write out our "whole" stars
for (int j = 0; j < (int) i; j++)
{
Console.Write("()");
}
// Then, if needed, write out the "half" star
if (i % 1 >= .5M) Console.Write("(");
Console.WriteLine();
}
GetKeyFromUser("\n\nDone! Press any key to exit...");
//以.5为增量从.5循环到10(“M”表示数字是十进制的)
对于(十进制i=0.5M;i=0.5M)控制台;
Console.WriteLine();
}
GetKeyFromUser(“\n\n完成!按任意键退出…”);
输出
for(int s=0;s<0.5;s++)
此循环一次,而不是零次。稍后使用时,s
将用作测试。在这种情况下,您很幸运,但一般来说,将一个双精度值与另一个相等值(=0.5)进行比较从来都不是一个好主意,如果可以的话,最好使用整数。例如,您可以使用一个int并检查为(int s=0;s<(int)stars;s++)添加半星(评级&1==1)
强制转换为int
也可以。啊..谢谢!我可能太累了,无法直接思考。现在是凌晨2:38…或者存储数学。截断会产生一个双变量,用作循环边界,稍后用作减法变量。
double dec = stars - Math.Truncate(stars);
// Loop from .5 to 10 in increments of .5 (the 'M' signifies that the number is a decimal)
for (decimal i = .5M; i <= 5; i += .5M)
{
Console.Write($"{i:0.0}: ");
// First write out our "whole" stars
for (int j = 0; j < (int) i; j++)
{
Console.Write("()");
}
// Then, if needed, write out the "half" star
if (i % 1 >= .5M) Console.Write("(");
Console.WriteLine();
}
GetKeyFromUser("\n\nDone! Press any key to exit...");