我有一个BigDecimal计算结果,我需要四舍五入到最接近的指定间隔(在这种情况下,这是金融市场的变动幅度)。
例如价格[T号]->舍入价格
100.1 [0.25] -> 100
100.2 [0.25] -> 100.25
100.1 [0.125] -> 100.125
100.2 [0.125] -> 100.25
谢谢。
更新:schnaader的解决方案,翻译成Java / BigDecimal术语:
price = price.divide(tick).setScale(0, RoundingMode.HALF_UP).multiply(tick)
您可以标准化刻度大小,然后使用通常的舍入方法:
100.1 [0.25] -> * (1/0.25) -> 400.4 [1] -> round -> 400 -> / (1/0.25) -> 100
100.2 [0.25] -> * (1/0.25) -> 400.8 [1] -> round -> 401 -> / (1/0.25) -> 100.25
所以应该是:
Price = Round(Price / Tick) * Tick;
还要注意,您似乎必须为BigDecimals设置正确的舍入模式。例如,请参见BigDecimal Docs。因此,您应该确保设置正确,并编写一些测试来检查代码的正确性。
p= p - p % t + ((p % t < t / 2) ? 0.0 : t);
//其中,p =价格,t =报价增量
这与“将股票价格调整为最接近的刻度大小]。
schnaader提供的答案是正确的,但是缺少一些内容。
ArithmeticException
除法功能中可能出现的BigDecimal
这是我的解决方案。解释它会花费很多时间。我建议您尝试一些示例以尝试一下。查找功能roundTick()
。
import static java.math.RoundingMode.HALF_UP;
import java.math.BigDecimal;
/**
* Utility class for stock price related operations.
*/
public final class PriceFormatter {
public static final float DELTA = 0.0001f;
private PriceFormatter() {
}
/**
* Rounds the price to the nearest tick size.
*
* @param price price
* @param tickSize tick size
* @return price rounded to the nearest tick size
*/
public static final float roundTick(final float price, final float tickSize) {
if (tickSize < DELTA) {
return price;
}
if (!isRoundingNeeded(price, tickSize)) {
return price;
}
final BigDecimal p = new BigDecimal(price);
final BigDecimal t = new BigDecimal(tickSize);
final BigDecimal roundedPrice = p.divide(t, 0, HALF_UP).multiply(t);
return roundedPrice.floatValue();
}
/**
* Checks whether price needs rounding to the nearest tick size.
*
* @param price price
* @param tickSize tick size
* @return true, if rounding is needed; false otherwise
*/
public static final boolean isRoundingNeeded(final float price, final float tickSize) {
final int mult = calculateTickMultiplier(tickSize);
final int mod = (int) (tickSize * mult);
final float reminder = (((price * mult) % mult) % mod);
final boolean needsRounding = reminder > DELTA;
return needsRounding;
}
public static final int calculateTickMultiplier(final float tickSize) {
int result = 1;
while (((tickSize * result) < 1) || (((tickSize * result) - (int) (tickSize * result)) > DELTA)) {
result *= 10;
}
return result;
}
}