|
|
@@ -0,0 +1,60 @@
|
|
|
+package com.etotem.cfc.util;
|
|
|
+
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.*;
|
|
|
+
|
|
|
+class SpearmanUtilTest {
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void perfectPositiveRankCorrelation() {
|
|
|
+ // x 与 y 完全同序 → rho = 1
|
|
|
+ List<BigDecimal> x = Arrays.asList(new BigDecimal("1"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"));
|
|
|
+ List<BigDecimal> y = Arrays.asList(new BigDecimal("1"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"));
|
|
|
+ double rho = SpearmanUtil.spearmanRho(x, y);
|
|
|
+ assertEquals(1.0, rho, 1e-9);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void perfectNegativeRankCorrelation() {
|
|
|
+ List<BigDecimal> x = Arrays.asList(new BigDecimal("1"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"));
|
|
|
+ List<BigDecimal> y = Arrays.asList(new BigDecimal("4"), new BigDecimal("3"), new BigDecimal("2"), new BigDecimal("1"));
|
|
|
+ double rho = SpearmanUtil.spearmanRho(x, y);
|
|
|
+ assertEquals(-1.0, rho, 1e-9);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void tiedRanksHandled() {
|
|
|
+ // 有并列值时使用平均秩;x 与 y 逐项同值(含并列) → rho = 1
|
|
|
+ List<BigDecimal> x = Arrays.asList(new BigDecimal("1"), new BigDecimal("1"), new BigDecimal("2"));
|
|
|
+ List<BigDecimal> y = Arrays.asList(new BigDecimal("1"), new BigDecimal("1"), new BigDecimal("2"));
|
|
|
+ double rho = SpearmanUtil.spearmanRho(x, y);
|
|
|
+ assertEquals(1.0, rho, 1e-9);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void shortSeriesReturnsZero() {
|
|
|
+ // 少于 3 个配对点不计算(对应设计:单对象 ≥3 配对才参与)
|
|
|
+ List<BigDecimal> x = Arrays.asList(new BigDecimal("1"), new BigDecimal("2"));
|
|
|
+ List<BigDecimal> y = Arrays.asList(new BigDecimal("1"), new BigDecimal("2"));
|
|
|
+ assertEquals(0.0, SpearmanUtil.spearmanRho(x, y), 1e-9);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void fisherZAverageRestoresPositiveRho() {
|
|
|
+ // 两个 rho=0.6 的对象 z 均值还原 → 仍约 0.6
|
|
|
+ double avg = SpearmanUtil.fisherZAverage(new double[]{0.6, 0.6});
|
|
|
+ assertEquals(0.6, avg, 1e-6);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void fisherZAverageHandlesExtremeRho() {
|
|
|
+ // rho 接近 ±1 时 z 变换仍有限(这里验证不抛异常且符号正确)
|
|
|
+ double avg = SpearmanUtil.fisherZAverage(new double[]{0.99, 0.95});
|
|
|
+ assertTrue(avg > 0.9);
|
|
|
+ }
|
|
|
+}
|