mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Make behaviour of remainder of division for floating point numbers compatible with most of DBMS #7323
This commit is contained in:
parent
b8cc2bee53
commit
10355a2850
@ -100,10 +100,12 @@ template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfModulo
|
||||
{
|
||||
using Type = typename Construct<
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
sizeof(B)>::Type;
|
||||
using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||
Float64,
|
||||
typename Construct<
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
sizeof(B)>::Type>;
|
||||
};
|
||||
|
||||
template <typename A> struct ResultOfNegate
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <Common/Exception.h>
|
||||
#include <DataTypes/NumberTraits.h>
|
||||
@ -86,8 +87,15 @@ struct ModuloImpl
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
||||
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
|
||||
if constexpr (std::is_floating_point_v<ResultType>)
|
||||
{
|
||||
return ResultType(a) - trunc(ResultType(a) / ResultType(b)) * ResultType(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
||||
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
@ -102,6 +102,7 @@ using FunctionModulo = FunctionBinaryArithmetic<ModuloImpl, NameModulo, false>;
|
||||
void registerFunctionModulo(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionModulo>();
|
||||
factory.registerAlias("mod", "modulo", FunctionFactory::CaseInsensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,10 +14,17 @@ struct ModuloOrZeroImpl
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
{
|
||||
if (unlikely(divisionLeadsToFPE(a, b)))
|
||||
return 0;
|
||||
if constexpr (std::is_floating_point_v<ResultType>)
|
||||
{
|
||||
return ResultType(a) - floor(ResultType(a) / ResultType(b)) * ResultType(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely(divisionLeadsToFPE(a, b)))
|
||||
return 0;
|
||||
|
||||
return ModuloImpl<A, B>::template apply<Result>(a, b);
|
||||
return ModuloImpl<A, B>::template apply<Result>(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
3
tests/queries/0_stateless/01412_mod_float.reference
Normal file
3
tests/queries/0_stateless/01412_mod_float.reference
Normal file
@ -0,0 +1,3 @@
|
||||
1 -1 1 -1
|
||||
0.125 -0.125 0.125 -0.125
|
||||
1 -1 1 -1
|
3
tests/queries/0_stateless/01412_mod_float.sql
Normal file
3
tests/queries/0_stateless/01412_mod_float.sql
Normal file
@ -0,0 +1,3 @@
|
||||
WITH 8.5 AS a, 2.5 AS b SELECT a % b, -a % b, a % -b, -a % -b;
|
||||
WITH 10.125 AS a, 2.5 AS b SELECT a % b, -a % b, a % -b, -a % -b;
|
||||
WITH 8.5 AS a, 2.5 AS b SELECT mod(a, b), MOD(-a, b), modulo(a, -b), moduloOrZero(-a, -b);
|
Loading…
Reference in New Issue
Block a user