当我尝试这个乘法编译器时出现整数溢出错误
int main(){
long long int x;
x = 55201 * 55201;
printf("%lld", x);
return 0;
}
但是当我使用pow()函数执行相同的操作时,我不会收到任何错误。
int main(){
long long int x;
x = pow(55201, 2);
printf("%lld", x);
return 0;
}
为什么会这样?我必须使用第一个代码。
答案 0 :(得分:3)
您需要像这样更改代码
int main(){
long long int x;
x = 55201LL * 55201LL; // <--- notice the LL
printf("%lld", x);
return 0;
}
将乘法设为long long
当您使用pow
功能时,您不会发现任何问题,因为pow
使用浮点进行计算。
答案 1 :(得分:1)
这里(Linux 64bits,gcc 5.2.1),55201
是一个大小为4的整数文字,表达式55201 * 55201
似乎存储在4的整数中,然后才分配给你long long int
。
一种选择是在乘法之前将因子存储在另一个变量中,以增加范围。
int main(){
long long int x, factor;
factor = 55201;
x = factor * factor;
printf("%lld", x);
return 0;
}
答案 2 :(得分:1)
在下面的代码中,55201默认为整数,然后相乘,结果在乘法后也是一个整数。在private void ADD_button_Click(object sender, EventArgs e)
{
// Getting data from DataGridView
DataTable myDt = new DataTable();
myDt = GetDTfromDGV(dataGridView);
// Writing to sql
WriteToSQL(myDt);
}
private DataTable GetDTfromDGV(DataGridView dgv)
{
// Making our DataTable
DataTable dt = new DataTable();
foreach (DataGridViewColumn column in dgv.Columns)
{
dt.Columns.Add(column.Name, typeof(string));
}
// Getting data
foreach (DataGridViewRow dgvRow in dgv.Rows)
{
DataRow dr = dt.NewRow();
for (int col = 0; col < dgv.Columns.Count; col++)
{
dr[col] = dgvRow.Cells[col].Value;
}
dt.Rows.Add(dr);
}
// removing empty rows
for (int row = dt.Rows.Count - 1; row >= 0; row--)
{
bool flag = true;
for (int col = 0; col < dt.Columns.Count; col++)
{
if (dt.Rows[row][col] != DBNull.Value)
{
flag = false;
break;
}
}
if (flag == true)
{
dt.Rows.RemoveAt(row);
}
}
return dt;
}
private void WriteToSQL(DataTable dt)
{
using (SqlConnection con = new SqlConnection(sqlconn))
{
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con);
// Setting the database table name
sqlBulkCopy.DestinationTableName = "[AnimalProductsCoSD].[CoSD].[ERSBusinessLogic]";
// Mapping the DataTable columns with that of the database table
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[0].ColumnName, "ERSBusinessLogic_ID"));
Convert.ToString(sqlBulkCopy.ColumnMappings.Add(dt.Columns[1].ColumnName, "ERSBusinessLogic_Formula"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[2].ColumnName, "ERSBusinessLogic_InputsCount"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[3].ColumnName, "ERSBusinessLogic_Inputs"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[4].ColumnName, "ERSBusinessLogic_ConvFactorID"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[5].ColumnName, "ERSBusinessLogic_MacroID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[6].ColumnName, "ERSBusinessLogic_DataSeries"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[7].ColumnName, "ERSBusinessLogic_InputTimeDimensionValue"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[8].ColumnName, "ERSBusinessLogic_InputTimeDimensionType"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[9].ColumnName, "ERSBusinessLogic_GeographyDimensionID"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[10].ColumnName, "ERSBusinessLogic_InputsUnitsIDs"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[11].ColumnName, "ERSBusinessLogic_Type"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[12].ColumnName, "ERSBusinessLogic_PrivacyID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[13].ColumnName, "ERSBusinessLogic_LongDesc"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[14].ColumnName, "ERSBusinessLogic_InputSources"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[15].ColumnName, "ERSBusinessLogic_OutputName"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[16].ColumnName, "ERSBusinessLogic_OutputUnitID"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[17].ColumnName, "ERSBusinessLogic_OutputDestination"));
Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[18].ColumnName, "ERSBusinessLogic_OutputTimeDimensionValue"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[19].ColumnName, "ERSBusinessLogic_OutputTimeDimensionType"));
Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[20].ColumnName, "ERSBusinessLogic_GroupID"));
con.Open();
sqlBulkCopy.WriteToServer(dt);
}
}
乘法期间将计算但是它似乎溢出整数限制...这就是编译器生成警告的原因,即code optimization phase
integer overflow
int main(){
long long int x;
x = 55201 * 55201;
printf("%lld", x);
return 0;
}
声明如下:
pow
但在第二种情况下,函数double pow(double x, double y);
将每个参数都视为pow
,所以现在“55201”和“2”将被隐式转换为double
,现在计算发生在双精度所以计算结果后不会超过双重类型的限制......因此double
要建立相同的结果,但使用方法1可以完成如下:
the compiler will not generate any overflow message in this case.
就是这样......理解......是否有帮助。
答案 3 :(得分:0)
问题是操作是使用最大类型的操作数执行的,至少是int
(C standard, 6.3.1.8)。赋值只是C中的另一个表达式,=
左侧的类型与右侧操作无关。
在您的平台上,两个常量都适合int
,因此表达式55201 * 55201
的计算结果为int
。问题是结果不适合int
,因此会产生溢出。
有符号整数溢出是未定义的行为。这意味着一切都会发生。幸运的是,你的编译器足够聪明,可以检测到这一点,并警告你,而不是计算机跳出窗口。简而言之:避免它!
解决方案是使用可以保存完整结果的类型执行操作。简短计算得出产品需要32位来表示值。因此unsigned long
就足够了。如果需要有符号整数,则需要另一位符号,即33位。这种类型现在非常罕见,所以你必须使用至少有64位的long long
。 (即使它在你的平台上有64位,也不要试图使用long
;这会使你的代码实现定义,因此不可移植而没有任何好处。)< / p>
为此,您需要至少其中一个操作数以获得结果类型的类型:
x = 55201LL * 55201; // first factor is a long long constant
如果涉及变量,请使用强制转换:
long f1 = 55201; // an int is not guaranteed to hold this value!
x = (long long)f1 * 55201;
请注意,此处不使用L
后缀作为常量。它们将自动升级为最小的类型(至少int
),它可以代表值。
另一个表达式x = pow(55201, 2)
使用floating point function。因此,在调用double
之前,参数将转换为pow
。 double
结果由赋值运算符转换为左侧类型。
这有两个问题:
long long
。常见的IEEE754实现存在这个问题。 (这与此具体计算无关)作为一般规则,如果需要精确结果,则不应使用浮点运算。混合浮点和整数应该非常谨慎。