从总计中查找周数的公式

Formula to find week numbers from the Total

谁能帮我找出下面例子中的公式或数学术语。

Predefined sets stored in the system,
1 = Monday 
2 = Tuesday 
4 = Wednesday 
8 = Thursday 
16 = Friday 
32 = Saturday
64 = Sunday.

From the Total i need to retrieve the days from the predefined set, like,

Eg: 1
127 = This means i have to take All Days in the week from the predefined sets.

Eg: 2
80 = This means i have to take Friday and Sunday only

Eg: 3
7 = This means i have to take Monday, Tuesday and Wednesday.

提前致谢。

我想在评论中添加它,但还没有声誉。

为了解决这个问题,你可以看看二进制索引。

它们是 2 的幂,例如:

2^0 = 1
2^1 = 2
2^2 = 4

把2^2之前的所有数字都算起来就是3,也就是2^2-1,所以你可以通过数字相加来区分天数的所有组合。

反向技巧是不断减去仍然小于所要求数字的最高数字并不断重复。

你可以取一个 bitwise AND & 和日期值并取这一天。

const
    days = { Monday: 1, Tuesday: 2, Wednesday: 4, Thursday: 8, Friday: 16, Saturday: 32, Sunday: 64 },
    getDays = value => Object.keys(days).filter(day => value & days[day]);

console.log(getDays(127)); // All Days
console.log(getDays(80));  // Friday, Sunday
console.log(getDays(7));   // Monday, Tuesday, Wednesday
.as-console-wrapper { max-height: 100% !important; top: 0; }

Java 9 及更高版本的解决方案,因为我知道 Java 和 JavaScript 解决方案都会有所帮助。首先,我们需要

private static final Map<DayOfWeek, Integer> dayBits = new EnumMap<>(
        Map.of(DayOfWeek.MONDAY, 0x1, DayOfWeek.TUESDAY, 0x2, 
                DayOfWeek.WEDNESDAY, 0x4, DayOfWeek.THURSDAY, 0x8,
                DayOfWeek.FRIDAY, 0x10, DayOfWeek.SATURDAY, 0x20,
                DayOfWeek.SUNDAY, 0x40));

那我们可以做

int total = 80;
Set<DayOfWeek> days = Stream.of(DayOfWeek.values())
        .filter(dow -> (total & dayBits.get(dow)) > 0)
        .collect(Collectors.toCollection(() -> EnumSet.noneOf(DayOfWeek.class)));
System.out.println(days);

我们得到的输出是

[FRIDAY, SUNDAY]

后面的代码片段也适用于 Java 8,只是您需要一种更冗长的地图初始化方式。

您可能已经注意到,数字 1、2、4、8 等代表二进制数的位。 1 是二进制的 00000001,2 是二进制的 00000010,4 是 00000100,等等。所以我们的任务是找出总数的哪些位被设置。 127 是 01111111,所有七位都已设置。 80 是 01010000,设置了周五和周日的位。要查明某个位是否已设置,请使用(单个)& 运算符。如果包括星期一,total & 1 将产生 1,如果不包括,它将产生 0。同样,如果包括星期二,total & 2 将产生 2,如果不包括,则为 0。

我更喜欢读写十六进制的位常量,比如0x20。因为 0b0010_0000 太长了,而且从 32 开始并不清楚设置了哪一位(除非你真的很擅长二进制数,而且你不应该期望阅读你程序的每个人都是)。

当然,除了 built-in DayOfWeek 枚举之外,我不会梦想将星期几表示为其他任何东西。