mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +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
|
template <typename A, typename B> struct ResultOfModulo
|
||||||
{
|
{
|
||||||
using Type = typename Construct<
|
using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||||
is_signed_v<A> || is_signed_v<B>,
|
Float64,
|
||||||
false,
|
typename Construct<
|
||||||
sizeof(B)>::Type;
|
is_signed_v<A> || is_signed_v<B>,
|
||||||
|
false,
|
||||||
|
sizeof(B)>::Type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A> struct ResultOfNegate
|
template <typename A> struct ResultOfNegate
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <Common/Exception.h>
|
#include <Common/Exception.h>
|
||||||
#include <DataTypes/NumberTraits.h>
|
#include <DataTypes/NumberTraits.h>
|
||||||
@ -86,8 +87,15 @@ struct ModuloImpl
|
|||||||
template <typename Result = ResultType>
|
template <typename Result = ResultType>
|
||||||
static inline Result apply(A a, B b)
|
static inline Result apply(A a, B b)
|
||||||
{
|
{
|
||||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
if constexpr (std::is_floating_point_v<ResultType>)
|
||||||
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
|
{
|
||||||
|
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
|
#if USE_EMBEDDED_COMPILER
|
||||||
|
@ -102,6 +102,7 @@ using FunctionModulo = FunctionBinaryArithmetic<ModuloImpl, NameModulo, false>;
|
|||||||
void registerFunctionModulo(FunctionFactory & factory)
|
void registerFunctionModulo(FunctionFactory & factory)
|
||||||
{
|
{
|
||||||
factory.registerFunction<FunctionModulo>();
|
factory.registerFunction<FunctionModulo>();
|
||||||
|
factory.registerAlias("mod", "modulo", FunctionFactory::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,17 @@ struct ModuloOrZeroImpl
|
|||||||
template <typename Result = ResultType>
|
template <typename Result = ResultType>
|
||||||
static inline Result apply(A a, B b)
|
static inline Result apply(A a, B b)
|
||||||
{
|
{
|
||||||
if (unlikely(divisionLeadsToFPE(a, b)))
|
if constexpr (std::is_floating_point_v<ResultType>)
|
||||||
return 0;
|
{
|
||||||
|
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
|
#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