소스 검색

Initial commit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nh99sysrj6-blip 6 달 전
커밋
96e4468fa4
42개의 변경된 파일과 6434개의 추가작업 그리고 0개의 파일을 삭제
  1. 120 0
      AtName.py
  2. 225 0
      FindRE.py
  3. 49 0
      Ocr2List.py
  4. 9 0
      binomial.py
  5. 162 0
      convert2one.py
  6. 20 0
      copyFast.sh
  7. 12 0
      decrypt.sh
  8. 12 0
      encrypt.sh
  9. 51 0
      gameLife.py
  10. BIN
      html小工具/双重验证密码生成器-显示密钥版本-六个数字.7z
  11. 1 0
      html小工具/密码管理.html
  12. 997 0
      html小工具/小工具合集.html
  13. 129 0
      html小工具/文件加密工具 - XOR Secure.html
  14. 108 0
      html小工具/文件合并工具.html
  15. 136 0
      html小工具/方程数值解计算器.html
  16. 136 0
      html小工具/概率分布计算器.html
  17. 52 0
      html小工具/求导.html
  18. 143 0
      html小工具/直方图计算工具.html
  19. 97 0
      html小工具/等差乘等比求和计算器.html
  20. 130 0
      html小工具/统计计算工具.html
  21. 273 0
      html小工具/解析几何计算工具.html
  22. 12 0
      hypergeometric.py
  23. 263 0
      mathCheat.py
  24. 23 0
      orgnazieFolder.sh
  25. 19 0
      processTxt.py
  26. 767 0
      rationalsqrt2.dart
  27. 25 0
      removeEmptyFolders.sh
  28. 29 0
      word2pptx.py
  29. 201 0
      大纲设计工具.html
  30. 68 0
      小分表/excel.sh/average.sh
  31. 475 0
      小分表/excel.sh/excel.sh.md
  32. 50 0
      小分表/excel.sh/filter.sh
  33. 27 0
      小分表/excel.sh/main.sh
  34. 66 0
      小分表/excel.sh/output.sh
  35. 46 0
      小分表/excel.sh/sort.sh
  36. 524 0
      小分表/python版/main.py
  37. 7 0
      小分表/小分表.html
  38. 31 0
      快捷键.py
  39. BIN
      换座位/Temp.xlsx
  40. 841 0
      换座位/座位表.html
  41. 98 0
      换座位/换座位.py
  42. BIN
      综合素质表脚本.7z

+ 120 - 0
AtName.py

@@ -0,0 +1,120 @@
+#用于查找没交作业的学生
+import re
+
+def main():
+   count = 0
+   input = """21:285G
+
+0.00
+KB/s5G51%
+56人已支付
+洪平江已支付¥16.00
+陈修玉的爸… 已支付¥16.00杨宸睿妈妈… 已支付¥16.00陶永辉家长…已支付¥16.00陶永辉会考费
+高一峻妈妈… 已支付¥16.00李诚喜妈妈…已支付¥1600于カロメメCメ1+10.00孙李锦钊妈… 已支付¥16.00会考费用
+高瑞璠爸爸… 已支付¥16.00李奕莹的妈… 已支付¥16.00施微微妈妈… 已支付¥16.00谭闰之妈妈… 已支付¥39.00梁颂源父亲…已支付¥16.00陈瑾璇妈妈… 已支付¥16.00陈瑾璇
+罗梦楚妈妈…已支付¥16.00陈维海妈妈… 已支付¥16.00李云杰家长…已支付¥16.00李云杰
+吴耀鸿妈妈… 已支付¥16.00我是张剑锋… 已支付¥16.00刘庆明妈妈… 已支付¥16.00陈贤睿妈妈… 已支付¥16.00陈贤睿
+章何铖妈妈… 已支付¥16.00李滴妈妈13… 已支付¥16.00王思懿的爸爸 已支付¥16.00吴寒现妈妈
+吴寒现已支付¥16.00
+陈记娴爸爸… 已支付¥16.00卢玥熹妈妈… 已支付¥16.00卢玥熹
+罗浩铭妈妈… 已支付¥16.00--Hしし1--
+罗浩铭
+吴媛媛家长… 已支付¥16.00罗朝胤爸爸… 已支付¥16.00徐正阳妈
+徐正阳已支付¥16.00
+陈浩爸爸(… 已支付¥16.00杨杭榕母亲…已支付¥16.00杨杭榕
+杨锦程父亲…已支付¥16.00曾熠妈妈-.已支付¥16.00曾熠
+车嘉瑜妈妈… 已支付¥16.00李世涛妈妈… 已支付¥16.00梁金豪妈妈… 已支付¥16.00梁金豪
+高高翔爸爸13…已支付¥16.00姜奕彤妈妈… 已支付¥16.00吕思娴妈妈… 已支付¥16.00叶锡妈妈(… 已支付¥16.00郑传承妈妈已支付¥16.00马梓寒妈妈… 已支付¥16.00杨思彤妈妈… 已支付¥16.00罗子程妈妈… 已支付¥16.00罗子程
+肖力铭爸爸…已支付¥16.00肖力铭
+张家旗的妈… 已支付¥16.00罗尔君妈妈… 已支付¥16.00普子烨妈妈… 已支付¥16.00
+張张奕轩爸爸… 已支付¥16.00陆乙菘妈妈… 已支付¥16.00陆乙菘考试费
+朱槟妈妈(…
+朱槟会考费已支付¥16.00俞勇任妈妈… 已支付¥16.00蔡白俊妈妈… 已支付¥16.00姚明梁家长已支付¥16.00
+李致成妈妈… 已支付¥16.00
+收到的钱将存入零钱
+"""
+   names = ["何奇锴",
+"刘庆明",
+"杨棋竣",
+"张剑锋",
+"蔡白俊",
+"俞勇任",
+"林福任",
+"陆乙菘",
+"李诚嘉",
+"曾熠",
+"郑传承",
+"杨锦程",
+"陶永辉",
+"李致成",
+"钱潇",
+"朱槟",
+"李世涛",
+"赵德涵",
+"张家旗",
+"杨宸睿",
+"高一峻",
+"李滴",
+"肖力铭",
+"马梓寒",
+"普子烨",
+"杨建枢",
+"张奕轩",
+"梁金豪",
+"吴耀鸿",
+"罗朝胤",
+"鲁子平",
+"詹健",
+"陈浩",
+"孙李锦钊",
+"管晨寓",
+"高瑞璠",
+"王启颂",
+"梁颂源",
+"高翔",
+"石泰锦钖",
+"姚明梁",
+"周财豪",
+"章何铖",
+"罗浩铭",
+"陈维海",
+"吴寒现",
+"徐正阳",
+"罗子程",
+"陈瑾璇",
+"潘志婷",
+"罗梦楚",
+"刘思羽",
+"叶锡",
+"陈修玉",
+"施微微",
+"谭闰之",
+"杨思彤",
+"卢玥熹",
+"李奕莹",
+"李彬慈",
+"陈贤睿",
+"李宝妹",
+"陈记娴",
+"洪爽笑",
+"吴媛媛",
+"李云杰",
+"阳静",
+"车嘉瑜",
+"罗尔君",
+"李梓熙",
+"姜奕彤",
+"吕思娴",
+"王思懿",
+"龙思淇",
+"何青卓",
+"杨杭榕"
+]
+   for name in names:
+      if input.find(name) == -1:
+        print(name,end=",")
+        count += 1
+   print("共",count,"人未交")
+      
+if __name__ == '__main__':
+   main()

+ 225 - 0
FindRE.py

@@ -0,0 +1,225 @@
+#用于查找重复交钱的家长
+def main():
+   count = 0
+   input = """ 14:00
+5G
+25届高三(45)班(151)
+.eo
+樱花支付了你发起的群收款
+07:00
+孔凡景的妈妈电话17787306921支付了你发起的
+群收款
+08:13
+李四锦15912802117
+恭喜发财!
+微信红包
+10:50
+唐文辉爸爸13887327538支付了你发起的群收款
+唐文辉爸爸13887327538
+1951
+.
+止怀发起的群收款
+红河州测试卷费每人16.6元,早位家长上
+已支付¥16.80
+67人已支付
+钱文杰18987185803已支付¥16.80
+子针姐组18587115872 Bt16 80
+刘的妈路15087347535已支付¥16.80
+郑创家长18987004087 14 80
+农妈路15891932048已支付¥16.80
+11:12
+白航宇爸爸15187362277支付了你发起的群收款 14:00
+5G
+く
+25届高三(45)班(151)Δ
+李四锦15912802117
+老师你好!这是李俊余的试卷
+费麻烦你收一下,谢谢辛苦了!
+昨天21:09
+孔凡景的妈妈电话17787306921
+¥这个是孔凡景的试..
+微信红包
+孔凡景的妈妈电话17787306921
+老师你好!请你收一下
+昨天21:38
+纳正峰妈妈15125542223支付了你发起的群收款
+昨天21:46
+孔德雨妈妈13187950966支付了你发起的群收款蔡活鑫爸爸15126223116支付了你发起的群收款
+昨天23:19
+大民
+北方民族大学授予建水实验
+中学优质生源基地 14:00
+5G
+く
+25届高三(45)班(151)Δ
+王灿妈妈15287385376支付了你发起的群收款白春元爸爸13769477865支付了你发起的群收款
+昨天20:45
+冉子周妈妈14787912748支付了你发起的群收款
+黎智爸爸支付了你发起的群收款
+马旭萌妈妈13668728935
+老师好,请收一下马旭萌费用,
+没读清楚就发了,给你们添麻
+烦了!谢谢!
+唐信业妈妈15087351237支付了你发起的群收款陈诺妈妈13208776039支付了你发起的群收款李程仰爸爸15008883786支付了你发起的群收款者思名爸爸,18214385576.支付了你发起的群收
+款
+昨天21:02
+李四锦15912802117
+恭喜发财,大吉大利
+微信红包 13:59
+5G
+く
+25届高三(45)班(151)Δ
+朱博伦妈妈支付了你发起的群收款<
+马宇妈妈15094186061支付了你发起的群收款李欣龙妈妈13529467178支付了你发起的群收款
+昨天20:12
+王心怡爸爸13529488565支付了你发起的群收款马秀莹(杨涵誉妈妈)13887573387支付了你发起
+的群收款
+昨天20:31
+知足常乐
+好的,后面统计的时候会退还
+您
+陈汪源.爸爸13988466788:我们家
+交重了陈汪源
+陈汪源
+8988 8788
+姜满曦妈妈13887332233支付了你发起的群收款罗启豪妈妈13408982620支付了你发起的群收款
+昨天20:38 13:59
+5G
+く
+25届高三(45)班(151)
+陈汪源.爸爸13988466788支付了你发起的群收
+款
+钱文杰爸爸18987185803支付了你发起的群收
+款
+向围燃妈妈15257841558支付了你发起的群收款
+陈汪源.爸爸13988466788
+我们家交重了陈汪源
+昨天19:58
+刘智强爸爸支付了你发起的群收款
+王梓任爸爸13529489273支付了你发起的群收款白春元妈妈18887408964支付了你发起的群收款
+昨天20:01
+罗承秋妈妈15008801734支付了你发起的群收款杨兆宇妈妈15911378366支付了你发起的群收款
+昨天20:06
+コ
+马旭萌妈妈1366872893
+马旭萌 13:59
+5G
+く
+25届高三(45)班(151)
+卢卡斯爸爸13887523788支付了你发起的群收款
+昨天19:33
+魏子针姐姐18587115872支付了你发起的群收款王糠18214120291支付了你发起的群收款杨鹏妈妈13529196171支付了你发起的群收款李欢颜妈妈15008816935支付了你发起的群收款
+昨天19:39
+罗惠妈妈15987361746支付了你发起的群收款季轩逸妈妈13988834999支付了你发起的群收款张奕宁妈妈14787773016支付了你发起的群收款陈汪源妈妈13529997053支付了你发起的群收款丁林宇妈妈18183632912支付了你发起的群收款翁顺博的妈妈13408994288支付了你发起的群收
+款
+蒋雨璇妈妈13508837611支付了你发起的群收款
+昨天19:44
+杨光银妈妈18787956758支付了你发起的群收款 13:59
+5G
+く
+25届高三(45)班(151)
+杨璨宇妈妈18387788990支付了你发起的群收款白玺妈妈15924635807支付了你发起的群收款罗云月爸爸15969062666支付了你发起的群收款孙涵稀妈妈13529945455支付了你发起的群收款农哲妈妈15891932048支付了你发起的群收款
+昨天19:28
+羊虹燃妈妈15126201097支付了你发起的群收款何伟豪妈妈13887390927支付了你发起的群收款杨子贞妈妈18214337086支付了你发起的群收款储艺婷15911398928王旭敏妈妈支付了你发起的
+群收款
+刘桓的妈妈15087347535支付了你发起的群收款
+储艺婷15911398928王旭敏妈妈
+谢谢老师
+刘柏栋妈妈15808734361支付了你发起的群收款郑剑家长18987004087支付了你发起的群收款周婉婷妈妈-13988095352支付了你发起的群收
+款 13:59
+5G
+く
+25届高三(45)班(151)Δ
+刘恩源妈妈15987735479支付了你发起的群收款
+知足常乐
+辛苦各位家长上交一下州统测
+试卷费,交到上面的群收款里。
+不要直接在群里发红包转账,
+防止被其他家长误领@所有人
+丁忠兴妈妈13988028570支付了你发起的群收款丁逸飞爸爸15825209082支付了你发起的群收款
+昨天19:24
+吴槐午姐姐18214395122支付了你发起的群收款李然缘宇妈妈15925304084支付了你发起的群收
+款
+钟建航爸爸13988064349支付了你发起的群收款李博妈妈15368359085支付了你发起的群收款吴发亮姐姐18468061157支付了你发起的群收款合灿鑫爸爸15908773014支付了你发起的群收款白子懿家长15087344976支付了你发起的群收款盘成王妈妈13529944743支付了你发起的群收款陈治宇爸爸13887593677支付了你发起的群收款
+
+"""
+   names = ["陈诺",
+"李欢颜",
+"周婉婷",
+"马旭萌",
+"孔凡景",
+"刀家娴",
+"王心怡",
+"罗云月",
+"杨子贞",
+"杨光银",
+"王旭敏",
+"张奕宁",
+"罗承秋",
+"罗惠",
+"合灿鑫",
+"冉子周",
+"陈汪源",
+"白子懿",
+"何金周",
+"孙涵稀",
+"季轩逸",
+"向围燃",
+"钱文杰",
+"陈治宇",
+"翁顺博",
+"马宇",
+"杨涵誉",
+"李文楠",
+"李程仰",
+"丁忠兴",
+"朱博伦",
+"罗启豪",
+"蒋雨璇",
+"吴发亮",
+"王灿",
+"郑剑",
+"钟建航",
+"何伟豪",
+"唐文辉",
+"吴槐午",
+"李然缘宇",
+"蔡活鑫",
+"杨兆宇",
+"李俊余",
+"黎智",
+"刘智强",
+"白春元",
+"杨鹏",
+"岩肖权",
+"者思名",
+"王梓任",
+"纳正峰",
+"刘恩源",
+"李欣龙",
+"盘成王",
+"李文北",
+"农哲",
+"唐信业",
+"姜满曦",
+"刘柏栋",
+"李博",
+"魏子针",
+"羊虹燃",
+"刘桓",
+"丁俊杰",
+"卢卡斯",
+"白航宇",
+"孔德雨",
+"杨璨宇",
+"王糠",
+"丁逸飞",
+"白玺"]
+   for name in names:
+      if input.count(name) >= 2:
+        print(name,end=",")
+        count += 1
+   print("共",count,"人交重复")
+      
+if __name__ == '__main__':
+   main()

+ 49 - 0
Ocr2List.py

@@ -0,0 +1,49 @@
+import json
+from tencentcloud.common import credential
+from tencentcloud.common.profile.client_profile import ClientProfile
+from tencentcloud.common.profile.http_profile import HttpProfile
+from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
+from tencentcloud.ocr.v20181119 import ocr_client, models
+import base64
+ 
+def image_to_base64(image_path):
+    with open(image_path, "rb") as image_file:
+        encoded_string = base64.b64encode(image_file.read())
+        return encoded_string.decode("utf-8")  # 将bytes转换为字符串
+# 使用示例
+#image_path = "path/to/your/image.jpg"
+#base64_data = image_to_base64(image_path)
+#print(base64_data)
+
+def ocr(img_base64):
+    SecretId="AKIDypmtpbLcLtEfw3t84JOJCwV3iPhrCGdq"
+    SecretKey="MwKZFOMCE6oKuLdLnOn10wc27wkJcfTA"
+    try:
+    # 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
+    # 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
+    # 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
+        cred = credential.Credential(SecretId, SecretKey)
+    # 实例化一个http选项,可选的,没有特殊需求可以跳过
+        httpProfile = HttpProfile()
+        httpProfile.endpoint = "ocr.tencentcloudapi.com"
+
+    # 实例化一个client选项,可选的,没有特殊需求可以跳过
+        clientProfile = ClientProfile()
+        clientProfile.httpProfile = httpProfile
+    # 实例化要请求产品的client对象,clientProfile是可选的
+        client = ocr_client.OcrClient(cred, "ap-guangzhou", clientProfile)
+
+    # 实例化一个请求对象,每个接口都会对应一个request对象
+        req = models.GeneralBasicOCRRequest()
+        params = {
+            "ImageBase64": img_base64,
+            "LanguageType": "zh"
+        }
+        req.from_json_string(json.dumps(params))
+
+    # 返回的resp是一个GeneralBasicOCRResponse的实例,与请求对象对应
+        resp = client.GeneralBasicOCR(req)
+    # 输出json格式的字符串回包
+        print(resp.to_json_string())
+    except TencentCloudSDKException as err:
+        print(err)

+ 9 - 0
binomial.py

@@ -0,0 +1,9 @@
+#二项分布
+from fractions import Fraction
+from math import comb
+n=3
+p=Fraction(1,5)
+print("EX=",n*p)
+print("DX=",n*p*(1-p))
+for i in range(n+1):
+    print("P(X=",i,")=",comb(n,i)*pow(p,i)*pow(1-p,n-i))

+ 162 - 0
convert2one.py

@@ -0,0 +1,162 @@
+#将高考题md文档分割成单独的题目
+
+import re
+import os
+
+def parse_document(content):
+    """
+    解析文档内容,提取所有题目和对应的答案详解
+    """
+    # 分割题目部分和答案部分
+    parts = content.split("**《2024年新课标全国Ⅰ卷数学真题》参考答案**")
+
+    if len(parts) < 2:
+        return []
+
+    questions_part = parts[0]
+    answers_part = parts[1]
+
+    # 提取所有题目
+    questions = extract_questions(questions_part)
+
+    # 提取所有答案
+    answers = extract_answers(answers_part)
+
+    # 合并题目和答案
+    result = []
+    for i, (q_num, q_content) in enumerate(questions):
+        if i < len(answers):
+            result.append((q_num, q_content, answers[i][1]))
+
+    return result
+
+def extract_questions(content):
+    """
+    从题目部分提取所有题目
+    """
+    questions = []
+
+    # 匹配题目的正则表达式(匹配 "数字." 格式)
+    pattern = r'(\d+).(.*?)(?=\d+.|$)'
+    matches = re.finditer(pattern, content, re.DOTALL)
+
+    for match in matches:
+        question_num = match.group(1)
+        question_content = match.group(2).strip()
+        questions.append((question_num, question_content))
+
+    return questions
+
+def extract_answers(content):
+    """
+    从答案部分提取所有答案详解
+    """
+    answers = []
+
+    # 匹配答案的正则表达式
+    pattern = r'(\d+).(.*?)(?=\d+.|$)'
+    matches = re.finditer(pattern, content, re.DOTALL)
+
+    for match in matches:
+        answer_num = match.group(1)
+        answer_content = match.group(2).strip()
+
+        # 清理答案内容,移除开头的选项字母
+        answer_content = re.sub(r'^[A-D]', '', answer_content).strip()
+        answers.append((answer_num, answer_content))
+
+    return answers
+
+def get_question_type(question_num):
+    """
+    根据题号确定题目类型
+    """
+    num = int(question_num)
+    if 1 <= num <= 8:
+        return "单选"
+    elif 9 <= num <= 11:
+        return "多选"
+    elif 12 <= num <= 14:
+        return "填空"
+    else:
+        return "解答"
+
+def format_question_md(question_num, question_content, answer_content):
+    """
+    格式化单个题目为Markdown格式,答案用callouts隐藏
+    """
+    question_type = get_question_type(question_num)
+
+    # 添加元数据
+    metadata = f"""---
+Tags:
+  - 题库
+年份: 2024
+源卷: 全国1
+原题号: {question_num}
+题目类型: {question_type}
+知识点:
+  -
+难度:
+---
+
+"""
+
+    # 处理答案内容,每一行都加上 > 前缀
+    formatted_answer = ""
+    for line in answer_content.split('\n'):
+        if line.strip():  # 非空行
+            formatted_answer += f"> {line}\n"
+        else:  # 空行
+            formatted_answer += ">\n"
+
+    md_content = f"""{metadata}# 第{question_num}题
+
+## 题目
+
+{question_content}
+
+## 答案
+
+> [!question]- 点击查看答案
+{formatted_answer}
+"""
+    return md_content
+
+def save_questions(questions_data, output_dir="questions"):
+    """
+    保存所有题目为单独的Markdown文件
+    """
+    if not os.path.exists(output_dir):
+        os.makedirs(output_dir)
+
+    for question_num, question_content, answer_content in questions_data:
+        filename = f"{question_num}.md"
+        filepath = os.path.join(output_dir, filename)
+
+        md_content = format_question_md(question_num, question_content, answer_content)
+
+        with open(filepath, 'w', encoding='utf-8') as f:
+            f.write(md_content)
+
+        print(f"已保存: {filename}")
+
+def main():
+    # 读取文档内容(这里使用文档2的内容)
+    with open('document2.txt', 'r', encoding='utf-8') as f:
+        content = f.read()
+
+    # 解析文档
+    questions_data = parse_document(content)
+
+    if not questions_data:
+        print("未能解析出题目数据")
+        return
+
+    print(f"成功解析 {len(questions_data)} 道题目")
+
+    # 保存为单独的Markdown文件
+    save_questions(questions_data)
+
+if __name__ == "__main__":
+    main()

+ 20 - 0
copyFast.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+#此脚本用于将downloads目录下最新的ppt拷贝到u盘,并弹出u盘
+
+# 获取U盘路径
+usb_path="/run/media/nonvioce/U盘"
+
+# 检查是否有U盘插入
+if [ -d "$usb_path" ]; then
+  # 获取Downloads文件夹中的所有文件
+  files=$(ls /home/nonvioce/Downloads)
+
+  # 找到最新的文件
+  latest_file=$(ls -t /home/nonvioce/Downloads | head -n1)
+  echo $latest_file
+  # 将最新的文件复制到U盘
+  cp /home/nonvioce/Downloads/$latest_file "$usb_path"
+  umount /run/media/nonvioce/U盘
+else
+  echo "U盘未插入"
+fi

+ 12 - 0
decrypt.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+#用于解密文件, 使用方法:./decrypt.sh output.txt decrypted.txt mypassword
+if [ $# -ne 3 ]; then
+    echo "Usage: $0 <input_file> <output_file> <password>"
+    exit 1
+fi
+
+input_file=$1
+output_file=$2
+password=$3
+
+openssl enc -d -aes-256-cbc -in "$input_file" -out "$output_file" -k "$password"

+ 12 - 0
encrypt.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+#用于加密文件, 使用方法:./encrypt.sh input.txt output.txt mypassword
+if [ $# -ne 3 ]; then
+    echo "Usage: $0 <input_file> <output_file> <password>"
+    exit 1
+fi
+
+input_file=$1
+output_file=$2
+password=$3
+
+openssl enc -aes-256-cbc -salt -in "$input_file" -out "$output_file" -k "$password"

+ 51 - 0
gameLife.py

@@ -0,0 +1,51 @@
+import random
+
+
+#主类
+class Timer:
+    def __init__(self):
+        self.time = 0
+
+    def update(self):
+        self.time += 1
+
+
+#交易中心
+class TradeCenter:
+    def __init__(self):
+        #定义当前价格
+        self.price = random.uniform(1,100)#当前股价
+        self.total = 100000#共有多少股
+        self.majorNum = 100000#当前系统持有股
+        self.majorNumOld = 100000#前一天系统持有多少股
+
+    def update(self):
+        #更新价格
+        a = random.uniform(-1,1) + (self.majorNum - self.majorNumOld)/self.total
+        if abs(a)<=0.2*a:
+            self.price = self.price + a
+        elif a>0:
+            self.price = self.price*1.2
+        else:
+            self.price = self.price*0.8
+        #存储前一天持有股
+        self.majorNumOld = self.majorNum
+    
+    def buy(a,self):
+        self.majorNum += a
+
+    def sell(a,self):
+        self.majorNum -= a
+
+class Person:
+    def __init__(self):
+        self.money = 100#可用金额
+        self.Num = 0#持有股数
+    def buy(a,TradeCenter,self):
+        self.money -= a*TradeCenter.price
+        self.Num += a
+        TradeCenter.sell(a)
+    def sell(a,TradeCenter,self):
+        self.money += a*TradeCenter.price
+        self.Num -= a
+        TradeCenter.buy(a)

BIN
html小工具/双重验证密码生成器-显示密钥版本-六个数字.7z


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 0
html小工具/密码管理.html


+ 997 - 0
html小工具/小工具合集.html

@@ -0,0 +1,997 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>数学工具套件</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+    <style>
+        .tool-content { display: none; }
+        .tool-content.active { display: block; }
+        .nav-btn.active { 
+            background-color: #3B82F6; 
+            color: white;
+        }
+    </style>
+</head>
+<body class="bg-gray-100 min-h-screen">
+    <!-- 导航栏 -->
+    <nav class="bg-white shadow-lg">
+        <div class="max-w-7xl mx-auto px-4">
+            <div class="flex justify-between py-3">
+                <div class="flex space-x-4 overflow-x-auto">
+                    <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="encrypt">文件加密</button>
+                    <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="series">等差乘等比</button>
+                    <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="stats">统计计算</button>
+                    <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="histogram">直方图</button>
+                    <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="geometry">解析几何</button>
+                     <button class="nav-btn px-4 py-2 rounded-lg hover:bg-blue-50" data-tool="distribution">概率分布</button>
+                </div>
+            </div>
+        </div>
+    </nav>
+
+    <!-- 工具容器 -->
+    
+        <!-- 文件加密工具 -->
+        <div id="encrypt" class="tool-content">
+            <!-- ... 原有文件加密内容 ... -->
+            <!DOCTYPE html>
+            <html lang="en">
+            <head>
+                <meta charset="UTF-8">
+                <meta name="viewport" content="width=device-width, initial-scale=1.0">
+                <title>文件加密工具 - XOR Secure</title>
+                <script src="https://cdn.tailwindcss.com"></script>
+            </head>
+            <body class="bg-gray-100 min-h-screen p-8">
+                <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
+                    <h1 class="text-3xl font-bold text-gray-800 mb-6 text-center">文件加密工具</h1>
+                    
+                    <div class="space-y-4">
+                        <!-- 文件上传区域 -->
+                        <div class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
+                            <input type="file" id="fileInput" class="hidden" />
+                            <label for="fileInput" class="cursor-pointer bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 transition-colors">
+                                选择文件
+                            </label>
+                            <p class="text-gray-500 mt-2" id="fileName">未选择任何文件</p>
+                        </div>
+            
+                        <!-- 密钥输入 -->
+                        <div class="space-y-2">
+                            <label class="block text-gray-700">加密密钥:</label>
+                            <input type="password" id="keyInput" 
+                                class="w-full p-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+                                placeholder="输入加密/解密密钥">
+                        </div>
+            
+                        <!-- 操作按钮 -->
+                        <div class="grid grid-cols-2 gap-4">
+                            <button onclick="processFile('encrypt')" 
+                                class="bg-green-500 text-white p-3 rounded-lg hover:bg-green-600 transition-colors flex items-center justify-center">
+                                <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
+                                </svg>
+                                加密文件
+                            </button>
+                            <button onclick="processFile('decrypt')" 
+                                class="bg-purple-500 text-white p-3 rounded-lg hover:bg-purple-600 transition-colors flex items-center justify-center">
+                                <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z"/>
+                                </svg>
+                                解密文件
+                            </button>
+                        </div>
+            
+                        <!-- 状态提示 -->
+                        <div id="status" class="text-center text-gray-500 h-6"></div>
+            
+                        <!-- 下载链接 -->
+                        <div id="downloadLink" class="hidden text-center">
+                            <a class="text-blue-500 hover:underline cursor-pointer">下载处理后的文件</a>
+                        </div>
+                    </div>
+                </div>
+            
+                <script>
+                    const fileInput = document.getElementById('fileInput');
+                    const fileName = document.getElementById('fileName');
+                    const keyInput = document.getElementById('keyInput');
+                    const status = document.getElementById('status');
+                    const downloadLink = document.getElementById('downloadLink');
+            
+                    // 文件选择处理
+                    fileInput.addEventListener('change', function(e) {
+                        fileName.textContent = e.target.files[0] ? e.target.files[0].name : '未选择任何文件';
+                    });
+            
+                    // 核心加密/解密函数
+                    async function processFile(mode) {
+                        const file = fileInput.files[0];
+                        const key = keyInput.value;
+                        
+                        if (!file || !key) {
+                            alert('请先选择文件并输入密钥');
+                            return;
+                        }
+            
+                        status.textContent = '处理中...';
+                        downloadLink.classList.add('hidden');
+            
+                        try {
+                            const fileBuffer = await file.arrayBuffer();
+                            const processedBuffer = xorProcessing(new Uint8Array(fileBuffer), key);
+                            
+                            const processedBlob = new Blob([processedBuffer], { type: file.type });
+                            const url = URL.createObjectURL(processedBlob);
+                            
+                            downloadLink.querySelector('a').onclick = () => {
+                                const ext = mode === 'encrypt' ? '.encrypted' : '.decrypted';
+                                const link = document.createElement('a');
+                                link.href = url;
+                                link.download = `${file.name}${ext}`;
+                                link.click();
+                                URL.revokeObjectURL(url);
+                            };
+                            
+                            downloadLink.classList.remove('hidden');
+                            status.textContent = '处理完成!点击下方链接下载';
+                        } catch (error) {
+                            status.textContent = '处理失败:' + error.message;
+                        }
+                    }
+            
+                    // XOR加密/解密算法
+                    function xorProcessing(data, key) {
+                        const keyBytes = Array.from(key).map(c => c.charCodeAt(0));
+                        return data.map((byte, index) => 
+                            byte ^ keyBytes[index % keyBytes.length]
+                        );
+                    }
+                </script>
+            
+                <style>
+                    /* 自定义加载动画 */
+                    [aria-busy="true"]::after {
+                        content: "";
+                        @apply inline-block ml-2 w-4 h-4 border-2 border-current border-t-transparent rounded-full;
+                        animation: spin 0.75s linear infinite;
+                    }
+            
+                    @keyframes spin {
+                        to { transform: rotate(360deg); }
+                    }
+                </style>
+            </body>
+            </html>
+            
+        </div>
+
+        <!-- 等差乘等比求和 -->
+        <div id="series" class="tool-content">
+            <div class="min-h-[60vh] flex items-center justify-center">
+            <!-- ... 原有等差乘等比内容 ... -->
+            <!DOCTYPE html>
+            <html>
+            <head>
+                <meta charset="UTF-8">
+                <title>等差乘等比求和计算器</title>
+                <script src="https://cdn.tailwindcss.com"></script>
+                <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+            </head>
+            <body class="min-h-screen bg-gray-100 flex items-center justify-center">
+                <div class="bg-white p-8 rounded-lg shadow-lg w-96">
+                    <h1 class="text-2xl font-bold mb-6 text-gray-800">错位相减法计算器</h1>
+                    
+                    <div class="space-y-4">
+                        <div>
+                            <label class="block text-sm font-medium text-gray-700 mb-1">a (系数):</label>
+                            <input type="text" id="a" class="w-full border rounded px-3 py-2" placeholder="如: 3/4 或 0.75">
+                        </div>
+                        <div>
+                            <label class="block text-sm font-medium text-gray-700 mb-1">b (常数项):</label>
+                            <input type="text" id="b" class="w-full border rounded px-3 py-2" placeholder="如: 1/2 或 0.5">
+                        </div>
+                        <div>
+                            <label class="block text-sm font-medium text-gray-700 mb-1">q (公比):</label>
+                            <input type="text" id="q" class="w-full border rounded px-3 py-2" placeholder="如: 2 或 1/3">
+                        </div>
+                        <div>
+                            <label class="block text-sm font-medium text-gray-700 mb-1">m (指数调整):</label>
+                            <input type="text" id="m" class="w-full border rounded px-3 py-2" placeholder="整数,如: 2">
+                        </div>
+                    </div>
+            
+                    <button onclick="calculate()" class="w-full bg-blue-500 text-white py-2 px-4 rounded mt-6 hover:bg-blue-600 transition-colors">
+                        计算
+                    </button>
+            
+                    <div id="result" class="hidden mt-6 p-4 bg-gray-50 rounded">
+                        <p class="font-medium text-gray-800">结果公式:Sₙ = (A⋅n + B)qⁿ - B</p>
+                        <div class="mt-3 space-y-2">
+                            <p class="text-sm">A = <span id="A-value" class="font-mono text-blue-600"></span></p>
+                            <p class="text-sm">B = <span id="B-value" class="font-mono text-blue-600"></span></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            
+                <script>
+                    // 确保Fraction库可用性检查
+                    if (typeof Fraction === 'undefined') {
+                        alert('错误:分数库加载失败,请检查网络连接!');
+                    }
+            
+                    function parseInput(value) {
+                        try {
+                            return new Fraction(value);
+                        } catch (e) {
+                            throw new Error('无效的分数格式,请使用如 3/4 或 0.75 的格式');
+                        }
+                    }
+            
+                    function calculate() {
+                        try {
+                            // 检查Fraction库是否加载
+                            if (typeof Fraction === 'undefined') {
+                                throw new Error('分数库加载失败,请刷新页面重试');
+                            }
+            
+                            // 解析输入值
+                            const a = parseInput(document.getElementById('a').value);
+                            const b = parseInput(document.getElementById('b').value);
+                            const q = parseInput(document.getElementById('q').value);
+                            const m = parseInt(document.getElementById('m').value);
+            
+                            // 验证输入有效性
+                            if (isNaN(m)) throw new Error('m必须是整数');
+                            if (q.valueOf() === 1) throw new Error('q不能等于1');
+            
+                            // 计算调整系数
+                            const qPower = q.pow(m + 1);
+                            const adjustedA = a.mul(qPower);
+                            const adjustedB = b.mul(qPower);
+            
+                            // 计算核心参数
+                            const qMinus1 = q.sub(1);
+                            const A = adjustedA.div(qMinus1);
+                            const B = adjustedB.sub(A).div(qMinus1);
+            
+                            // 显示结果
+                            document.getElementById('result').classList.remove('hidden');
+                            document.getElementById('A-value').textContent = A.toFraction();
+                            document.getElementById('B-value').textContent = B.toFraction();
+                            
+                        } catch (error) {
+                            alert(`计算错误: ${error.message}`);
+                        }
+                    }
+                </script>
+            </body>
+            </html>
+            
+        </div>
+
+        <!-- 统计计算工具 -->
+        <div id="stats" class="tool-content">
+            <!-- ... 原有统计计算内容 ... -->
+            <!DOCTYPE html>
+            <html lang="zh-cn">
+            <head>
+                <meta charset="UTF-8">
+                <meta name="viewport" content="width=device-width, initial-scale=1.0">
+                <title>统计计算工具</title>
+                <script src="https://cdn.tailwindcss.com"></script>
+                <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+            </head>
+            <body class="p-6 bg-gray-100">
+                <div class="max-w-2xl mx-auto space-y-8">
+                    <!-- 卡方计算 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">卡方计算(2×2列联表)</h2>
+                        <div class="grid grid-cols-2 gap-4 mb-4">
+                            <input type="number" id="k2a" class="p-2 border rounded" placeholder="a">
+                            <input type="number" id="k2b" class="p-2 border rounded" placeholder="b">
+                            <input type="number" id="c" class="p-2 border rounded" placeholder="c">
+                            <input type="number" id="d" class="p-2 border rounded" placeholder="d">
+                        </div>
+                        <button onclick="calculateChiSquare()" class="w-full bg-purple-500 text-white p-2 rounded hover:bg-purple-600">
+                            计算卡方值
+                        </button>
+                        <div id="chi2-results" class="mt-4 space-y-2"></div>
+                    </div>
+            
+                    <!-- 线性回归计算 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">一元线性回归</h2>
+                        <div class="space-y-4">
+                            <div>
+                                <label class="block mb-2">X 值(空格分隔)</label>
+                                <input type="text" id="x-values" class="w-full p-2 border rounded" placeholder="例如: 1 2 3 4 5">
+                            </div>
+                            <div>
+                                <label class="block mb-2">Y 值(空格分隔)</label>
+                                <input type="text" id="y-values" class="w-full p-2 border rounded" placeholder="例如: 2 4 6 8 10">
+                            </div>
+                            <button onclick="calculateRegression()" class="w-full bg-orange-500 text-white p-2 rounded hover:bg-orange-600">
+                                计算回归参数
+                            </button>
+                            <div id="regression-results" class="mt-4 space-y-2"></div>
+                        </div>
+                    </div>
+                </div>
+            
+                <script>
+                    // 卡方计算
+                    function calculateChiSquare() {
+                        const a = parseInt(document.getElementById('k2a').value) || 0;
+                        const b = parseInt(document.getElementById('k2b').value) || 0;
+                        const c = parseInt(document.getElementById('c').value) || 0;
+                        const d = parseInt(document.getElementById('d').value) || 0;
+                        
+                        const n = a + b + c + d;
+                        const numerator = n * Math.pow((a * d - b * c), 2);
+                        const denominator = (a + b) * (c + d) * (a + c) * (b + d);
+                        
+                        const K2 = new Fraction(numerator).div(denominator);
+                        const results = document.getElementById('chi2-results');
+                        
+                        results.innerHTML = `
+                            <p class="font-medium">卡方值 K² = ${K2.toFraction()}</p>
+                            <p class="font-medium">近似值 ≈ ${K2.valueOf().toFixed(4)}</p>
+                        `;
+                    }
+            
+                    // 线性回归计算
+                    // 修改后(使用IIFE封装)
+(function(){
+    function calculateRegression() {
+        // ...原有代码...
+         const xInput = document.getElementById('x-values').value.split(' ').filter(Boolean);
+                        const yInput = document.getElementById('y-values').value.split(' ').filter(Boolean);
+                        const results = document.getElementById('regression-results');
+                        
+                        if (xInput.length !== yInput.length) {
+                            results.innerHTML = '<p class="text-red-500">错误:X 和 Y 的数据量不一致</p>';
+                            return;
+                        }
+            
+                        const n = xInput.length;
+                        let sx = 0, sy = 0, sx2 = 0, sy2 = 0, sxy = 0;
+                        
+                        // 转换输入为数值
+                        const x = xInput.map(Number);
+                        const y = yInput.map(Number);
+            
+                        // 计算各项总和
+                        for (let i = 0; i < n; i++) {
+                            sx += x[i];
+                            sy += y[i];
+                            sx2 += x[i] ** 2;
+                            sy2 += y[i] ** 2;
+                            sxy += x[i] * y[i];
+                        }
+            
+                        // 计算统计量
+                        const xBar = sx / n;
+                        const yBar = sy / n;
+                        const sigmaX = sx2 - n * xBar ** 2;
+                        const sigmaY = sy2 - n * yBar ** 2;
+                        const sigmaXY = sxy - n * xBar * yBar;
+                        const r = sigmaXY / Math.sqrt(sigmaX * sigmaY);
+                        const b = sigmaXY / sigmaX;
+                        const a = yBar - b * xBar;
+            
+                        // 计算残差平方和和决定系数
+                        let se2 = 0;
+                        for (let i = 0; i < n; i++) {
+                            se2 += (y[i] - b * x[i] - a) ** 2;
+                        }
+                        const R2 = 1 - (se2 / sigmaY);
+            
+                        // 格式化显示结果
+                        results.innerHTML = `
+                            <div class="space-y-2">
+                                <p>均值 x̄ = ${xBar.toFixed(4)}</p>
+                                <p>均值 ȳ = ${yBar.toFixed(4)}</p>
+                                <p>方差 Σ(x-x̄)² = ${sigmaX.toFixed(4)}</p>
+                                <p>方差 Σ(y-ȳ)² = ${sigmaY.toFixed(4)}</p>
+                                <p>协方差 Σ(x-x̄)(y-ȳ) = ${sigmaXY.toFixed(4)}</p>
+                                <p class="font-medium">相关系数 r = ${r.toFixed(4)}</p>
+                                <p class="font-medium">回归系数 b = ${b.toFixed(4)}</p>
+                                <p class="font-medium">截距 a = ${a.toFixed(4)}</p>
+                                <p>残差平方和 = ${se2.toFixed(4)}</p>
+                                <p class="font-medium">决定系数 R² = ${R2.toFixed(4)}</p>
+                            </div>
+                        `;
+    }
+    window.calculateRegression = calculateRegression;
+})();
+                    
+                </script>
+            </body>
+            </html>
+            
+        </div>
+
+        <!-- 直方图工具 -->
+        <div id="histogram" class="tool-content">
+            <!-- ... 原有直方图内容 ... -->
+            <!DOCTYPE html>
+            <html lang="zh-cn">
+            <head>
+                <meta charset="UTF-8">
+                <meta name="viewport" content="width=device-width, initial-scale=1.0">
+                <title>直方图分析工具</title>
+                <script src="https://cdn.tailwindcss.com"></script>
+                <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+            </head>
+            <body class="p-6 bg-gray-100">
+                <div class="max-w-2xl mx-auto">
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">直方图统计分析</h2>
+                        
+                        <!-- 输入区域 -->
+                        <div class="space-y-4">
+                            <div>
+                                <label class="block mb-2">左端点(a)</label>
+                                <input type="text" id="hist-a" class="w-full p-2 border rounded" placeholder="例如: 1/2 或 0.5">
+                            </div>
+                            <div>
+                                <label class="block mb-2">组距(d)</label>
+                                <input type="text" id="hist-d" class="w-full p-2 border rounded" placeholder="例如: 1/3 或 0.25">
+                            </div>
+                            <div>
+                                <label class="block mb-2">各组频率(空格分隔)</label>
+                                <input type="text" id="hist-f" class="w-full p-2 border rounded" placeholder="例如: 0.2 1/5 3/10">
+                            </div>
+                            <div>
+                                <label class="block mb-2">百分位数(可选)</label>
+                                <input type="text" id="hist-p" class="w-full p-2 border rounded" placeholder="例如: 0.75 或 3/4">
+                            </div>
+                            <button onclick="calculateHistogram()" class="w-full bg-indigo-500 text-white p-2 rounded hover:bg-indigo-600">
+                                开始计算
+                            </button>
+                        </div>
+            
+                        <!-- 结果显示区域 -->
+                        <div id="hist-results" class="mt-6 space-y-4"></div>
+                    </div>
+                </div>
+            
+                <script>
+                    function parseFractionInput(input) {
+                        try {
+                            if (input.includes('/')) {
+                                const [n, d] = input.split('/').map(Number)
+                                return new Fraction(n, d)
+                            }
+                            return new Fraction(parseFloat(input))
+                        } catch {
+                            return null
+                        }
+                    }
+            
+                    function calculateHistogram() {
+                        const results = document.getElementById('hist-results')
+                        results.innerHTML = ''
+            
+                        // 解析输入值
+                        const a = parseFractionInput(document.getElementById('hist-a').value)
+                        const d = parseFractionInput(document.getElementById('hist-d').value)
+                        const fInputs = document.getElementById('hist-f').value.split(' ').filter(Boolean)
+                        const pInput = document.getElementById('hist-p').value
+            
+                        // 验证输入有效性
+                        if (!a || !d || fInputs.length === 0) {
+                            results.innerHTML = '<p class="text-red-500">错误:请输入有效的输入值</p>'
+                            return
+                        }
+            
+                        // 转换频率为分数数组
+                        const f = fInputs.map(parseFractionInput).filter(f => f !== null)
+                        if (f.length !== fInputs.length) {
+                            results.innerHTML = '<p class="text-red-500">错误:包含无效的频率值</p>'
+                            return
+                        }
+            
+                        // 计算频率总和
+                        const sump = f.reduce((acc, val) => acc.add(val), new Fraction(0))
+                        if (!sump.equals(1)) {
+                            results.innerHTML = `<p class="text-red-500">错误:频率总和应为1(当前为${sump.toFraction()})</p>`
+                            return
+                        }
+            
+                        // 计算均值和方差
+                        let x = d.div(2)
+                        let s = new Fraction(0)
+                        const n = f.length
+                        
+                        for (let i = 0; i < n; i++) {
+                            x = x.add(a.add(d.mul(i)).mul(f[i]))
+                        }
+                        
+                        for (let i = 0; i < n; i++) {
+                            const mid = a.add(d.mul(i)).add(d.div(2))
+                            s = s.add(mid.sub(x).pow(2).mul(f[i]))
+                        }
+            
+                        // 显示基础统计量
+                        let output = `
+                            <div class="space-y-2">
+                                <p class="font-medium">均值 = ${x.toFraction()} ≈ ${x.valueOf().toFixed(4)}</p>
+                                <p class="font-medium">方差 = ${s.toFraction()} ≈ ${s.valueOf().toFixed(4)}</p>
+                        `
+            
+                        // 百分位数计算
+                        if (pInput) {
+                            const p = parseFractionInput(pInput)
+                            if (p && p.compare(0) > 0 && p.compare(1) < 0) {
+                                let m = new Fraction(0)
+                                for (let i = 0; i < n; i++) {
+                                    if (m.add(f[i]).compare(p) >= 0) {
+                                        const q = a.add(d.mul(i)).sub(m.sub(p).div(f[i-1]).mul(d))
+                                        const integer = q.floor()
+                                        const decimal = q.sub(integer)
+                                        output += `<p>${p.toFraction()} 分位数 = ${integer} + ${decimal.toFraction()}</p>`
+                                        break
+                                    }
+                                    m = m.add(f[i])
+                                }
+                            }
+                        }
+            
+                        // 中位数计算
+                        let m = new Fraction(0)
+                        for (let i = 0; i < n; i++) {
+                            if (m.add(f[i]).compare(0.5) >= 0) {
+                                const q = a.add(d.mul(i)).sub(m.sub(0.5).div(f[i-1]).mul(d))
+                                const integer = q.floor()
+                                const decimal = q.sub(integer)
+                                output += `<p class="font-medium">中位数 = ${integer} + ${decimal.toFraction()}</p>`
+                                break
+                            }
+                            m = m.add(f[i])
+                        }
+            
+                        output += '</div>'
+                        results.innerHTML = output
+                    }
+                </script>
+            </body>
+            </html>
+            
+        </div>
+
+        <!-- 解析几何工具 -->
+        <div id="geometry" class="tool-content">
+            <!-- ... 原有解析几何内容 ... -->
+            <!DOCTYPE html>
+            <html lang="zh-cn">
+            <head>
+                <meta charset="UTF-8">
+                <meta name="viewport" content="width=device-width, initial-scale=1.0">
+                <title>几何计算工具</title>
+                <script src="https://cdn.tailwindcss.com"></script>
+                <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+            </head>
+            <body class="p-6 bg-gray-100">
+                <div class="max-w-2xl mx-auto space-y-8">
+                    <!-- 点关于直线对称 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">点关于直线对称</h2>
+                        <div class="grid grid-cols-2 gap-4">
+                            <div>
+                                <label class="block mb-2">点坐标 (x,y)</label>
+                                <input type="text" id="pl-x" class="w-full p-2 border rounded" placeholder="x">
+                                <input type="text" id="pl-y" class="w-full p-2 border rounded mt-2" placeholder="y">
+                            </div>
+                            <div>
+                                <label class="block mb-2">直线方程 Ax+By+C=0</label>
+                                <input type="text" id="pl-A" class="w-full p-2 border rounded" placeholder="A">
+                                <input type="text" id="pl-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                                <input type="text" id="pl-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                            </div>
+                        </div>
+                        <button onclick="calcPointLineSymmetry()" class="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 mt-4">
+                            计算对称点
+                        </button>
+                        <div id="pl-result" class="mt-4 space-y-2"></div>
+                    </div>
+            
+                    <!-- 直线关于点对称 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">直线关于点对称</h2>
+                        <div class="grid grid-cols-2 gap-4">
+                            <div>
+                                <label class="block mb-2">直线方程 Ax+By+C=0</label>
+                                <input type="text" id="lp-A" class="w-full p-2 border rounded" placeholder="A">
+                                <input type="text" id="lp-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                                <input type="text" id="lp-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                            </div>
+                            <div>
+                                <label class="block mb-2">对称点 (x,y)</label>
+                                <input type="text" id="lp-x" class="w-full p-2 border rounded" placeholder="x">
+                                <input type="text" id="lp-y" class="w-full p-2 border rounded mt-2" placeholder="y">
+                            </div>
+                        </div>
+                        <button onclick="calcLinePointSymmetry()" class="w-full bg-green-500 text-white p-2 rounded hover:bg-green-600 mt-4">
+                            计算对称直线
+                        </button>
+                        <div id="lp-result" class="mt-4 space-y-2"></div>
+                    </div>
+            
+                    <!-- 直线关于直线对称 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">直线关于直线对称</h2>
+                        <div class="grid grid-cols-2 gap-4">
+                            <div>
+                                <label class="block mb-2">原直线 Px+Qy+R=0</label>
+                                <input type="text" id="ll-P" class="w-full p-2 border rounded" placeholder="P">
+                                <input type="text" id="ll-Q" class="w-full p-2 border rounded mt-2" placeholder="Q">
+                                <input type="text" id="ll-R" class="w-full p-2 border rounded mt-2" placeholder="R">
+                            </div>
+                            <div>
+                                <label class="block mb-2">对称轴 Ax+By+C=0</label>
+                                <input type="text" id="ll-A" class="w-full p-2 border rounded" placeholder="A">
+                                <input type="text" id="ll-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                                <input type="text" id="ll-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                            </div>
+                        </div>
+                        <button onclick="calcLineLineSymmetry()" class="w-full bg-purple-500 text-white p-2 rounded hover:bg-purple-600 mt-4">
+                            计算对称直线
+                        </button>
+                        <div id="ll-result" class="mt-4 space-y-2"></div>
+                    </div>
+            
+                    <!-- 三点求圆 -->
+                    <div class="bg-white rounded-lg shadow-md p-6">
+                        <h2 class="text-xl font-bold mb-4">三点确定圆的方程</h2>
+                        <div class="grid grid-cols-3 gap-4">
+                            <div>
+                                <label class="block mb-2">点1 (x,y)</label>
+                                <input type="text" id="c-x1" class="w-full p-2 border rounded" placeholder="x1">
+                                <input type="text" id="c-y1" class="w-full p-2 border rounded mt-2" placeholder="y1">
+                            </div>
+                            <div>
+                                <label class="block mb-2">点2 (x,y)</label>
+                                <input type="text" id="c-x2" class="w-full p-2 border rounded" placeholder="x2">
+                                <input type="text" id="c-y2" class="w-full p-2 border rounded mt-2" placeholder="y2">
+                            </div>
+                            <div>
+                                <label class="block mb-2">点3 (x,y)</label>
+                                <input type="text" id="c-x3" class="w-full p-2 border rounded" placeholder="x3">
+                                <input type="text" id="c-y3" class="w-full p-2 border rounded mt-2" placeholder="y3">
+                            </div>
+                        </div>
+                        <button onclick="calcCircle()" class="w-full bg-orange-500 text-white p-2 rounded hover:bg-orange-600 mt-4">
+                            计算圆方程
+                        </button>
+                        <div id="c-result" class="mt-4 space-y-2"></div>
+                    </div>
+                </div>
+            
+                <script>
+                    // 公共函数:解析分数输入
+                    function parseFraction(input) {
+                        try {
+                            if (input.includes('/')) {
+                                const [numerator, denominator] = input.split('/').map(Number)
+                                return new Fraction(numerator, denominator)
+                            }
+                            return new Fraction(parseFloat(input))
+                        } catch {
+                            return null
+                        }
+                    }
+            
+                    // 二阶行列式计算
+                    function det2(a, b, c, d) {
+                        return a.mul(d).sub(b.mul(c))
+                    }
+            
+                    // 解二元一次方程组
+                    function solveSystem(a1, b1, c1, a2, b2, c2) {
+                        const D = det2(a1, b1, a2, b2)
+                        if (D.valueOf() === 0) return [null, null]
+                        const Dx = det2(c1, b1, c2, b2)
+                        const Dy = det2(a1, c1, a2, c2)
+                        return [Dx.div(D), Dy.div(D)]
+                    }
+            
+                    // 点关于直线对称
+                    // 点关于直线对称
+function calcPointLineSymmetry() {
+    const result = document.getElementById('pl-result')
+    result.innerHTML = ''
+
+    // 解析输入
+    const x = parseFraction(document.getElementById('pl-x').value)
+    const y = parseFraction(document.getElementById('pl-y').value)
+    const A = parseFraction(document.getElementById('pl-A').value)
+    const B = parseFraction(document.getElementById('pl-B').value)
+    const C = parseFraction(document.getElementById('pl-C').value)
+
+    if (!x || !y || !A || !B || !C) {
+        result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+        return
+    }
+
+    // 构造方程组(修复方程构造)
+    const equation1 = A.mul(x).add(B.mul(y)).add(C.mul(2)).neg() // 正确构造方程右侧
+    const equation2 = B.mul(x).sub(A.mul(y)) 
+
+    const [m, n] = solveSystem(
+        A, B, equation1,       // 第一个方程: A*m + B*n = -(Ax + By + 2C)
+        B, A.mul(-1), equation2 // 第二个方程: B*m - A*n = Bx - Ay
+    )
+
+    if (m && n) {
+        result.innerHTML = `
+            <p class="font-medium">对称点坐标:</p>
+            <p>(${m.toFraction()}, ${n.toFraction()})</p>
+            <p>近似值: (${m.valueOf().toFixed(2)}, ${n.valueOf().toFixed(2)})</p>
+        `
+    } else {
+        result.innerHTML = '<p class="text-red-500">错误:无法求解,可能直线不存在对称点</p>'
+    }
+}
+            
+                    // 直线关于点对称
+                    function calcLinePointSymmetry() {
+                        const result = document.getElementById('lp-result')
+                        result.innerHTML = ''
+            
+                        const A = parseFraction(document.getElementById('lp-A').value)
+                        const B = parseFraction(document.getElementById('lp-B').value)
+                        const C = parseFraction(document.getElementById('lp-C').value)
+                        const x = parseFraction(document.getElementById('lp-x').value)
+                        const y = parseFraction(document.getElementById('lp-y').value)
+            
+                        if (!A || !B || !C || !x || !y) {
+                            result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+                            return
+                        }
+            
+                        const m = A.mul(-2).mul(x).sub(B.mul(2).mul(y)).sub(C)
+                        
+                        result.innerHTML = `
+                            <p class="font-medium">对称直线方程:</p>
+                            <p>${A.toFraction()}x + ${B.toFraction()}y + ${m.toFraction()} = 0</p>
+                            <p>近似值: ${A.valueOf().toFixed(2)}x + ${B.valueOf().toFixed(2)}y + ${m.valueOf().toFixed(2)} = 0</p>
+                        `
+                    }
+            
+                    // 直线关于直线对称
+                    function calcLineLineSymmetry() {
+                        const result = document.getElementById('ll-result')
+                        result.innerHTML = ''
+            
+                        const P = parseFraction(document.getElementById('ll-P').value)
+                        const Q = parseFraction(document.getElementById('ll-Q').value)
+                        const R = parseFraction(document.getElementById('ll-R').value)
+                        const A = parseFraction(document.getElementById('ll-A').value)
+                        const B = parseFraction(document.getElementById('ll-B').value)
+                        const C = parseFraction(document.getElementById('ll-C').value)
+            
+                        if (!P || !Q || !R || !A || !B || !C) {
+                            result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+                            return
+                        }
+            
+                        const k = P.mul(A).add(Q.mul(B)).mul(2).div(A.pow(2).add(B.pow(2)))
+                        const newP = P.sub(A.mul(k))
+                        const newQ = Q.sub(B.mul(k))
+                        const newR = R.sub(C.mul(k))
+            
+                        result.innerHTML = `
+                            <p class="font-medium">对称直线方程:</p>
+                            <p>${newP.toFraction()}x + ${newQ.toFraction()}y + ${newR.toFraction()} = 0</p>
+                            <p>近似值: ${newP.valueOf().toFixed(2)}x + ${newQ.valueOf().toFixed(2)}y + ${newR.valueOf().toFixed(2)} = 0</p>
+                        `
+                    }
+            
+                    // 三点确定圆
+                    function calcCircle() {
+                        const result = document.getElementById('c-result')
+                        result.innerHTML = ''
+            
+                        // 解析三个点坐标
+                        const x1 = parseFraction(document.getElementById('c-x1').value)
+                        const y1 = parseFraction(document.getElementById('c-y1').value)
+                        const x2 = parseFraction(document.getElementById('c-x2').value)
+                        const y2 = parseFraction(document.getElementById('c-y2').value)
+                        const x3 = parseFraction(document.getElementById('c-x3').value)
+                        const y3 = parseFraction(document.getElementById('c-y3').value)
+            
+                        if (!x1 || !y1 || !x2 || !y2 || !x3 || !y3) {
+                            result.innerHTML = '<p class="text-red-500">错误:请输入有效的坐标值</p>'
+                            return
+                        }
+            
+                        // 构造方程组
+                        const z1 = x1.pow(2).add(y1.pow(2))
+                        const z2 = x2.pow(2).add(y2.pow(2))
+                        const z3 = x3.pow(2).add(y3.pow(2))
+            
+                        const [D, E] = solveSystem(
+                            x1.sub(x2), y1.sub(y2), z2.sub(z1),
+                            x1.sub(x3), y1.sub(y3), z3.sub(z1)
+                        )
+            
+                        if (!D || !E) {
+                            result.innerHTML = '<p class="text-red-500">错误:三点共线或无法形成圆</p>'
+                            return
+                        }
+            
+                        const F = z1.neg().sub(D.mul(x1)).sub(E.mul(y1))
+                        const r2 = D.pow(2).add(E.pow(2)).sub(F.mul(4)).div(4)
+            
+                        result.innerHTML = `
+                            <div class="space-y-2">
+                                <p class="font-medium">圆方程参数:</p>
+                                <p>D = ${D.toFraction()}, E = ${E.toFraction()}, F = ${F.toFraction()}</p>
+                                <p>圆心坐标: (-${D.div(2).toFraction()}, -${E.div(2).toFraction()})</p>
+                                <p>半径平方: ${r2.toFraction()} ≈ ${r2.valueOf().toFixed(4)}</p>
+                            </div>
+                        `
+                    }
+                </script>
+            </body>
+            </html>
+            
+        </div>
+        <div id="distribution" class="tool-content">
+    <div class="min-h-[60vh] flex items-center justify-center">
+        <div class="max-w-2xl mx-auto space-y-8 p-6">
+            <!-- 二项分布计算器 -->
+            <div class="bg-white rounded-lg shadow-md p-6">
+                <h2 class="text-xl font-bold mb-4">二项分布计算器</h2>
+                <div class="space-y-4">
+                    <div>
+                        <label class="block mb-2">试验次数 (n)</label>
+                        <input type="number" id="bin-n" class="w-full p-2 border rounded">
+                    </div>
+                    <div>
+                        <label class="block mb-2">成功概率 (p)</label>
+                        <input type="text" id="bin-p" class="w-full p-2 border rounded" placeholder="例如: 0.5 或 1/3">
+                    </div>
+                    <button onclick="calculateBinomial()" class="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600">
+                        计算二项分布
+                    </button>
+                    <div id="bin-results" class="mt-4 space-y-2"></div>
+                </div>
+            </div>
+
+            <!-- 超几何分布计算器 -->
+            <div class="bg-white rounded-lg shadow-md p-6">
+                <h2 class="text-xl font-bold mb-4">超几何分布计算器</h2>
+                <div class="space-y-4">
+                    <div>
+                        <label class="block mb-2">总数 (N)</label>
+                        <input type="number" id="hyp-N" class="w-full p-2 border rounded">
+                    </div>
+                    <div>
+                        <label class="block mb-2">成功元素数 (M)</label>
+                        <input type="number" id="hyp-M" class="w-full p-2 border rounded">
+                    </div>
+                    <div>
+                        <label class="block mb-2">抽取数 (n)</label>
+                        <input type="number" id="hyp-n" class="w-full p-2 border rounded">
+                    </div>
+                    <button onclick="calculateHypergeometric()" class="w-full bg-green-500 text-white p-2 rounded hover:bg-green-600">
+                        计算超几何分布
+                    </button>
+                    <div id="hyp-results" class="mt-4 space-y-2"></div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+    </div>
+<script>
+// 步骤3:在现有脚本末尾添加概率计算函数
+(function(){
+    // 组合数计算函数
+    function combination(n, k) {
+        if (k > n) return 0;
+        if (k === 0 || k === n) return 1;
+        k = Math.min(k, n - k);
+        let result = 1;
+        for (let i = 1; i <= k; i++) {
+            result = result * (n - k + i) / i;
+        }
+        return Math.round(result);
+    }
+
+    // 二项分布计算
+    function calculateBinomial() {
+        try {
+            const n = parseInt(document.getElementById('bin-n').value);
+            const p = new Fraction(document.getElementById('bin-p').value);
+            const results = document.getElementById('bin-results');
+            
+            const EX = p.mul(n);
+            const DX = EX.mul(new Fraction(1).sub(p));
+            
+            results.innerHTML = `
+                <p class="font-medium">期望 EX = ${EX.toFraction()}</p>
+                <p class="font-medium">方差 DX = ${DX.toFraction()}</p>
+                <div class="mt-4 space-y-1">
+                    <p class="font-medium">概率分布:</p>
+                    ${Array.from({length: n+1}, (_,k) => 
+                        `<p>P(X = ${k}) = ${new Fraction(combination(n, k))
+                            .mul(p.pow(k))
+                            .mul(new Fraction(1).sub(p).pow(n - k)).toFraction()}</p>`
+                    ).join('')}
+                </div>
+            `;
+        } catch(e) {
+            alert('输入参数错误:' + e.message);
+        }
+    }
+
+    // 超几何分布计算
+    function calculateHypergeometric() {
+        try {
+            const N = parseInt(document.getElementById('hyp-N').value);
+            const M = parseInt(document.getElementById('hyp-M').value);
+            const n = parseInt(document.getElementById('hyp-n').value);
+            const results = document.getElementById('hyp-results');
+            
+            const EX = new Fraction(M * n, N);
+            const DX = new Fraction(M * (N - M) * n * (N - n), N * N * (N - 1));
+            
+            const m = Math.max(0, n - (N - M));
+            const r = Math.min(n, M);
+            
+            results.innerHTML = `
+                <p class="font-medium">期望 EX = ${EX.toFraction()}</p>
+                <p class="font-medium">方差 DX = ${DX.toFraction()}</p>
+                <div class="mt-4 space-y-1">
+                    <p class="font-medium">概率分布:</p>
+                    ${Array.from({length: r - m +1}, (_,i) => {
+                        const k = m + i;
+                        return `<p>P(X = ${k}) = ${new Fraction(
+                            combination(M, k) * combination(N - M, n - k), 
+                            combination(N, n)).toFraction()}</p>`;
+                    }).join('')}
+                </div>
+            `;
+        } catch(e) {
+            alert('输入参数错误:' + e.message);
+        }
+    }
+
+    // 暴露函数到全局
+    window.calculateBinomial = calculateBinomial;
+    window.calculateHypergeometric = calculateHypergeometric;
+})();
+</script>
+    <script>
+        // 导航切换功能调整
+        document.addEventListener('DOMContentLoaded', function() {
+            const navButtons = document.querySelectorAll('.nav-btn');
+            const toolContents = document.querySelectorAll('.tool-content');
+
+            // 默认激活第一个工具(文件加密)
+            toolContents[0].classList.add('active');
+            navButtons[0].classList.add('active');
+
+            navButtons.forEach(button => {
+                button.addEventListener('click', function() {
+                    const toolId = this.dataset.tool;
+
+                    navButtons.forEach(btn => btn.classList.remove('active'));
+                    toolContents.forEach(content => content.classList.remove('active'));
+
+                    this.classList.add('active');
+                    document.getElementById(toolId).classList.add('active');
+                });
+            });
+        });
+    </script>
+</body>
+</html>

+ 129 - 0
html小工具/文件加密工具 - XOR Secure.html

@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>文件加密工具 - XOR Secure</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+</head>
+<body class="bg-gray-100 min-h-screen p-8">
+    <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
+        <h1 class="text-3xl font-bold text-gray-800 mb-6 text-center">文件加密工具</h1>
+        
+        <div class="space-y-4">
+            <!-- 文件上传区域 -->
+            <div class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
+                <input type="file" id="fileInput" class="hidden" />
+                <label for="fileInput" class="cursor-pointer bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 transition-colors">
+                    选择文件
+                </label>
+                <p class="text-gray-500 mt-2" id="fileName">未选择任何文件</p>
+            </div>
+
+            <!-- 密钥输入 -->
+            <div class="space-y-2">
+                <label class="block text-gray-700">加密密钥:</label>
+                <input type="password" id="keyInput" 
+                    class="w-full p-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+                    placeholder="输入加密/解密密钥">
+            </div>
+
+            <!-- 操作按钮 -->
+            <div class="grid grid-cols-2 gap-4">
+                <button onclick="processFile('encrypt')" 
+                    class="bg-green-500 text-white p-3 rounded-lg hover:bg-green-600 transition-colors flex items-center justify-center">
+                    <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
+                    </svg>
+                    加密文件
+                </button>
+                <button onclick="processFile('decrypt')" 
+                    class="bg-purple-500 text-white p-3 rounded-lg hover:bg-purple-600 transition-colors flex items-center justify-center">
+                    <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z"/>
+                    </svg>
+                    解密文件
+                </button>
+            </div>
+
+            <!-- 状态提示 -->
+            <div id="status" class="text-center text-gray-500 h-6"></div>
+
+            <!-- 下载链接 -->
+            <div id="downloadLink" class="hidden text-center">
+                <a class="text-blue-500 hover:underline cursor-pointer">下载处理后的文件</a>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        const fileInput = document.getElementById('fileInput');
+        const fileName = document.getElementById('fileName');
+        const keyInput = document.getElementById('keyInput');
+        const status = document.getElementById('status');
+        const downloadLink = document.getElementById('downloadLink');
+
+        // 文件选择处理
+        fileInput.addEventListener('change', function(e) {
+            fileName.textContent = e.target.files[0] ? e.target.files[0].name : '未选择任何文件';
+        });
+
+        // 核心加密/解密函数
+        async function processFile(mode) {
+            const file = fileInput.files[0];
+            const key = keyInput.value;
+            
+            if (!file || !key) {
+                alert('请先选择文件并输入密钥');
+                return;
+            }
+
+            status.textContent = '处理中...';
+            downloadLink.classList.add('hidden');
+
+            try {
+                const fileBuffer = await file.arrayBuffer();
+                const processedBuffer = xorProcessing(new Uint8Array(fileBuffer), key);
+                
+                const processedBlob = new Blob([processedBuffer], { type: file.type });
+                const url = URL.createObjectURL(processedBlob);
+                
+                downloadLink.querySelector('a').onclick = () => {
+                    const ext = mode === 'encrypt' ? '.encrypted' : '.decrypted';
+                    const link = document.createElement('a');
+                    link.href = url;
+                    link.download = `${file.name}${ext}`;
+                    link.click();
+                    URL.revokeObjectURL(url);
+                };
+                
+                downloadLink.classList.remove('hidden');
+                status.textContent = '处理完成!点击下方链接下载';
+            } catch (error) {
+                status.textContent = '处理失败:' + error.message;
+            }
+        }
+
+        // XOR加密/解密算法
+        function xorProcessing(data, key) {
+            const keyBytes = Array.from(key).map(c => c.charCodeAt(0));
+            return data.map((byte, index) => 
+                byte ^ keyBytes[index % keyBytes.length]
+            );
+        }
+    </script>
+
+    <style>
+        /* 自定义加载动画 */
+        [aria-busy="true"]::after {
+            content: "";
+            @apply inline-block ml-2 w-4 h-4 border-2 border-current border-t-transparent rounded-full;
+            animation: spin 0.75s linear infinite;
+        }
+
+        @keyframes spin {
+            to { transform: rotate(360deg); }
+        }
+    </style>
+</body>
+</html>

+ 108 - 0
html小工具/文件合并工具.html

@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>文件合并工具</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <style>
+        .file-input::file-selector-button {
+            @apply bg-blue-500 text-white px-4 py-2 rounded-lg border-0 cursor-pointer transition-colors duration-200;
+        }
+        .file-input::file-selector-button:hover {
+            @apply bg-blue-600;
+        }
+        #downloadLink {
+            @apply text-blue-500 hover:text-blue-700 underline cursor-pointer;
+        }
+    </style>
+</head>
+<body class="bg-gray-100 min-h-screen p-8">
+    <div class="max-w-2xl mx-auto bg-white rounded-xl shadow-md p-6">
+        <h1 class="text-2xl font-bold text-gray-800 mb-6">文件合并工具</h1>
+        
+        <div class="space-y-4">
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-2">选择图片文件 (jpg/png)</label>
+                <input type="file" id="imageFile" accept="image/jpeg, image/png" class="file-input">
+                <div id="imageName" class="text-sm text-gray-500 mt-1"></div>
+            </div>
+
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-2">选择压缩包文件 (rar/zip)</label>
+                <input type="file" id="archiveFile" accept=".rar, .zip" class="file-input">
+                <div id="archiveName" class="text-sm text-gray-500 mt-1"></div>
+            </div>
+
+            <button onclick="processFiles()" class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition-colors duration-200">
+                开始合并
+            </button>
+
+            <div id="status" class="text-sm text-gray-600 mt-4"></div>
+            <div id="result" class="mt-4"></div>
+        </div>
+    </div>
+
+    <script>
+        const readFileAsBuffer = (file) => {
+            return new Promise((resolve) => {
+                const reader = new FileReader();
+                reader.onload = (e) => resolve(e.target.result);
+                reader.readAsArrayBuffer(file);
+            });
+        };
+
+        document.getElementById('imageFile').addEventListener('change', function(e) {
+            document.getElementById('imageName').textContent = e.target.files[0]?.name || '';
+        });
+
+        document.getElementById('archiveFile').addEventListener('change', function(e) {
+            document.getElementById('archiveName').textContent = e.target.files[0]?.name || '';
+        });
+
+        async function processFiles() {
+            const imageFile = document.getElementById('imageFile').files[0];
+            const archiveFile = document.getElementById('archiveFile').files[0];
+            const status = document.getElementById('status');
+            const result = document.getElementById('result');
+
+            status.textContent = '';
+            result.innerHTML = '';
+
+            if (!imageFile || !archiveFile) {
+                status.textContent = '请先选择两个文件!';
+                return;
+            }
+
+            try {
+                status.textContent = '文件处理中...';
+
+                // 读取文件内容
+                const [imageBuffer, archiveBuffer] = await Promise.all([
+                    readFileAsBuffer(imageFile),
+                    readFileAsBuffer(archiveFile)
+                ]);
+
+                // 合并文件
+                const combined = new Uint8Array(imageBuffer.byteLength + archiveBuffer.byteLength);
+                combined.set(new Uint8Array(imageBuffer), 0);
+                combined.set(new Uint8Array(archiveBuffer), imageBuffer.byteLength);
+
+                // 创建下载链接
+                const blob = new Blob([combined], { type: imageFile.type });
+                const url = URL.createObjectURL(blob);
+                
+                result.innerHTML = `
+                    <div class="text-green-600">
+                        合并成功!点击下载:
+                        <a id="downloadLink" href="${url}" download="${imageFile.name}">${imageFile.name}</a>
+                    </div>
+                `;
+                status.textContent = '';
+            } catch (error) {
+                status.textContent = '处理失败:' + error.message;
+            }
+        }
+    </script>
+</body>
+</html>

+ 136 - 0
html小工具/方程数值解计算器.html

@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>方程数值解计算器</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+</head>
+<body class="bg-gray-100 min-h-screen p-8">
+    <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
+        <h1 class="text-2xl font-bold text-gray-800 mb-6">方程数值解计算器</h1>
+        
+        <!-- 输入区域 -->
+        <div class="space-y-4">
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-2">方程 f(x) = </label>
+                <input type="text" id="equation" 
+                       class="w-full p-2 border rounded-md" 
+                       placeholder="例如:ln(x) + sin(x^2)"
+                       value="ln(x) + sin(x^2)">
+	<label class="block text-sm font-medium text-gray-700 mb-2">e为底用ln(x),10为底用log(x)</label>
+            </div>
+            
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block text-sm font-medium text-gray-700 mb-2">区间起点 a</label>
+                    <input type="number" id="a" step="0.1" value="0.5" 
+                           class="w-full p-2 border rounded-md">
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-700 mb-2">区间终点 b</label>
+                    <input type="number" id="b" step="0.1" value="2" 
+                           class="w-full p-2 border rounded-md">
+                </div>
+            </div>
+
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-2">误差容限</label>
+                <input type="number" id="tolerance" step="0.0001" value="0.0001" 
+                       class="w-full p-2 border rounded-md">
+            </div>
+        </div>
+
+        <!-- 操作按钮 -->
+        <button onclick="calculateRoot()" 
+                class="mt-6 w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition">
+            计算
+        </button>
+
+        <!-- 结果展示 -->
+        <div id="result" class="mt-6 space-y-2 hidden">
+            <h2 class="text-lg font-semibold text-gray-800">计算结果:</h2>
+            <pre class="bg-gray-50 p-4 rounded-md" id="result-content"></pre>
+        </div>
+
+        <div id="error" class="mt-4 text-red-600 hidden"></div>
+    </div>
+
+    <script>
+        function calculateRoot() {
+            document.getElementById('result').classList.add('hidden');
+            document.getElementById('error').classList.add('hidden');
+
+            try {
+                const equation = document.getElementById('equation').value;
+                const a = parseFloat(document.getElementById('a').value);
+                const b = parseFloat(document.getElementById('b').value);
+                const tolerance = parseFloat(document.getElementById('tolerance').value);
+
+                if (isNaN(a) || isNaN(b) || isNaN(tolerance)) {
+                    throw new Error('请输入有效的数值参数');
+                }
+                if (a >= b) {
+                    throw new Error('区间终点b必须大于起点a');
+                }
+
+                // 改进的表达式转换逻辑
+                const processedEquation = equation
+                    .replace(/ln\(/g, 'Math.log(')         // 先处理自然对数
+                    .replace(/log\(/g, 'Math.log10(')     // 处理十进制对数
+                    .replace(/e\^(\w+|\([^)]*\))/g, 'Math.exp($1)') // 处理自然指数
+                    .replace(/(sin|cos|tan|sqrt|exp)\(/gi, (m, p1) => `Math.${p1.toLowerCase()}(`) // 处理其他数学函数
+                    .replace(/([a-zA-Z0-9\)]+)\s*\^\s*([a-zA-Z0-9\(]+)/g, 'Math.pow($1, $2)') // 最后处理幂运算
+                    .replace(/Math\.Math\./g, 'Math.');   // 修复嵌套替换问题
+
+                const f = new Function('x', `return ${processedEquation};`);
+                
+                // 测试函数是否有效
+                if (isNaN(f(a)) || isNaN(f(b))) {
+                    throw new Error('方程表达式无效,请检查数学函数和运算符');
+                }
+
+                const startTime = performance.now();
+                let [root, iterations] = bisection(f, a, b, tolerance);
+                const duration = performance.now() - startTime;
+
+                const resultContent = document.getElementById('result-content');
+                resultContent.innerHTML = `根值:${root.toFixed(6)}\n迭代次数:${iterations}\n计算耗时:${duration.toFixed(2)}ms`;
+                document.getElementById('result').classList.remove('hidden');
+
+            } catch (error) {
+                document.getElementById('error').innerText = '错误:' + error.message;
+                document.getElementById('error').classList.remove('hidden');
+            }
+        }
+
+        function bisection(f, a, b, tolerance, maxIterations = 1000) {
+            if (f(a) * f(b) >= 0) {
+                throw new Error('函数在区间端点必须异号');
+            }
+
+            let c = a;
+            let iterations = 0;
+            
+            while ((b - a) >= tolerance && iterations < maxIterations) {
+                c = (a + b) / 2;
+                
+                if (f(c) === 0.0) {
+                    break;
+                } else if (f(c) * f(a) < 0) {
+                    b = c;
+                } else {
+                    a = c;
+                }
+                iterations++;
+            }
+
+            if (iterations >= maxIterations) {
+                throw new Error('超过最大迭代次数,可能未收敛');
+            }
+
+            return [c, iterations];
+        }
+    </script>
+</body>
+</html>

+ 136 - 0
html小工具/概率分布计算器.html

@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>概率分布计算器</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+</head>
+<body class="p-6 bg-gray-100">
+    <div class="max-w-2xl mx-auto space-y-8">
+        <!-- 二项分布计算器 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">二项分布计算器</h2>
+            <div class="space-y-4">
+                <div>
+                    <label class="block mb-2">试验次数 (n)</label>
+                    <input type="number" id="bin-n" class="w-full p-2 border rounded">
+                </div>
+                <div>
+                    <label class="block mb-2">成功概率 (p)</label>
+                    <input type="text" id="bin-p" class="w-full p-2 border rounded" placeholder="例如: 0.5 或 1/3">
+                </div>
+                <button onclick="calculateBinomial()" class="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600">
+                    计算二项分布
+                </button>
+                <div id="bin-results" class="mt-4 space-y-2"></div>
+            </div>
+        </div>
+
+        <!-- 超几何分布计算器 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">超几何分布计算器</h2>
+            <div class="space-y-4">
+                <div>
+                    <label class="block mb-2">总数 (N)</label>
+                    <input type="number" id="hyp-N" class="w-full p-2 border rounded">
+                </div>
+                <div>
+                    <label class="block mb-2">成功元素数 (M)</label>
+                    <input type="number" id="hyp-M" class="w-full p-2 border rounded">
+                </div>
+                <div>
+                    <label class="block mb-2">抽取数 (n)</label>
+                    <input type="number" id="hyp-n" class="w-full p-2 border rounded">
+                </div>
+                <button onclick="calculateHypergeometric()" class="w-full bg-green-500 text-white p-2 rounded hover:bg-green-600">
+                    计算超几何分布
+                </button>
+                <div id="hyp-results" class="mt-4 space-y-2"></div>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        // 组合数计算函数
+        function combination(n, k) {
+            if (k > n) return 0;
+            if (k === 0 || k === n) return 1;
+            k = Math.min(k, n - k);
+            let result = 1;
+            for (let i = 1; i <= k; i++) {
+                result = result * (n - k + i) / i;
+            }
+            return Math.round(result);
+        }
+
+        // 解析分数输入
+        function parseFraction(input) {
+            if (input.includes('/')) {
+                const [numerator, denominator] = input.split('/').map(Number);
+                return new Fraction(numerator, denominator);
+            }
+            return new Fraction(parseFloat(input));
+        }
+
+        // 二项分布计算
+        function calculateBinomial() {
+            const n = parseInt(document.getElementById('bin-n').value);
+            const p = parseFraction(document.getElementById('bin-p').value);
+            const results = document.getElementById('bin-results');
+            results.innerHTML = '';
+
+            const EX = p.mul(n);
+            const DX = EX.mul(new Fraction(1).sub(p));
+            
+            results.innerHTML += `<p class="font-medium">期望 EX = ${EX.toFraction()}</p>`;
+            results.innerHTML += `<p class="font-medium">方差 DX = ${DX.toFraction()}</p>`;
+            
+            const probList = document.createElement('div');
+            probList.className = 'mt-4 space-y-1';
+            probList.innerHTML = '<p class="font-medium">概率分布:</p>';
+            
+            for (let k = 0; k <= n; k++) {
+                const combVal = combination(n, k);
+                const prob = new Fraction(combVal)
+                    .mul(p.pow(k))
+                    .mul(new Fraction(1).sub(p).pow(n - k));
+                probList.innerHTML += `<p>P(X = ${k}) = ${prob.toFraction()}</p>`;
+            }
+            
+            results.appendChild(probList);
+        }
+
+        // 超几何分布计算
+        function calculateHypergeometric() {
+            const N = parseInt(document.getElementById('hyp-N').value);
+            const M = parseInt(document.getElementById('hyp-M').value);
+            const n = parseInt(document.getElementById('hyp-n').value);
+            const results = document.getElementById('hyp-results');
+            results.innerHTML = '';
+
+            const EX = new Fraction(M * n, N);
+            const DX = new Fraction(M * (N - M) * n * (N - n), N * N * (N - 1));
+            
+            results.innerHTML += `<p class="font-medium">期望 EX = ${EX.toFraction()}</p>`;
+            results.innerHTML += `<p class="font-medium">方差 DX = ${DX.toFraction()}</p>`;
+            
+            const m = Math.max(0, n - (N - M));
+            const r = Math.min(n, M);
+            const probList = document.createElement('div');
+            probList.className = 'mt-4 space-y-1';
+            probList.innerHTML = '<p class="font-medium">概率分布:</p>';
+            
+            for (let k = m; k <= r; k++) {
+                const numerator = combination(M, k) * combination(N - M, n - k);
+                const denominator = combination(N, n);
+                const prob = new Fraction(numerator, denominator);
+                probList.innerHTML += `<p>P(X = ${k}) = ${prob.toFraction()}</p>`;
+            }
+            
+            results.appendChild(probList);
+        }
+    </script>
+</body>
+</html>

+ 52 - 0
html小工具/求导.html

@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>导数计算器</title>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.11.1/math.js"></script>
+    <style>
+        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
+        .container { background-color: #f5f5f5; padding: 20px; border-radius: 8px; }
+        input { width: 300px; padding: 8px; margin: 10px 0; }
+        button { background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
+        button:hover { background-color: #45a049; }
+        #result { margin-top: 20px; font-weight: bold; }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h2>导数计算器</h2>
+        <p>输入函数表达式(使用 x 作为变量)(ln x 请写成log(x)):</p>
+        <input type="text" id="functionInput" placeholder="例如:x^2 + 3*x + sin(x)" onkeypress="handleEnter(event)">
+        <br>
+        <button onclick="calculateDerivative()">计算导数</button>
+        <div id="result"></div>
+    </div>
+
+    <script>
+        function calculateDerivative() {
+            const input = document.getElementById('functionInput').value;
+            const resultDiv = document.getElementById('result');
+            
+            try {
+                // 使用 math.js 计算导数
+                const derivative = math.derivative(input, 'x');
+                
+                // 将结果转换为字符串并简化显示
+                const resultString = derivative.toString()
+                    .replace(/(\^)/g, '<sup>$1</sup>')
+                    .replace(/\*/g, '');
+                
+                resultDiv.innerHTML = `导数结果:<span style="color: #2c3e50;">${resultString}</span>`;
+            } catch (error) {
+                resultDiv.innerHTML = `<span style="color: red;">错误:${error.message}</span>`;
+            }
+        }
+
+        function handleEnter(event) {
+            if (event.key === 'Enter') {
+                calculateDerivative();
+            }
+        }
+    </script>
+</body>
+</html>

+ 143 - 0
html小工具/直方图计算工具.html

@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>直方图分析工具</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+</head>
+<body class="p-6 bg-gray-100">
+    <div class="max-w-2xl mx-auto">
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">直方图统计分析</h2>
+            
+            <!-- 输入区域 -->
+            <div class="space-y-4">
+                <div>
+                    <label class="block mb-2">左端点(a)</label>
+                    <input type="text" id="hist-a" class="w-full p-2 border rounded" placeholder="例如: 1/2 或 0.5">
+                </div>
+                <div>
+                    <label class="block mb-2">组距(d)</label>
+                    <input type="text" id="hist-d" class="w-full p-2 border rounded" placeholder="例如: 1/3 或 0.25">
+                </div>
+                <div>
+                    <label class="block mb-2">各组频率(空格分隔)</label>
+                    <input type="text" id="hist-f" class="w-full p-2 border rounded" placeholder="例如: 0.2 1/5 3/10">
+                </div>
+                <div>
+                    <label class="block mb-2">百分位数(可选)</label>
+                    <input type="text" id="hist-p" class="w-full p-2 border rounded" placeholder="例如: 0.75 或 3/4">
+                </div>
+                <button onclick="calculateHistogram()" class="w-full bg-indigo-500 text-white p-2 rounded hover:bg-indigo-600">
+                    开始计算
+                </button>
+            </div>
+
+            <!-- 结果显示区域 -->
+            <div id="hist-results" class="mt-6 space-y-4"></div>
+        </div>
+    </div>
+
+    <script>
+        function parseFractionInput(input) {
+            try {
+                if (input.includes('/')) {
+                    const [n, d] = input.split('/').map(Number)
+                    return new Fraction(n, d)
+                }
+                return new Fraction(parseFloat(input))
+            } catch {
+                return null
+            }
+        }
+
+        function calculateHistogram() {
+            const results = document.getElementById('hist-results')
+            results.innerHTML = ''
+
+            // 解析输入值
+            const a = parseFractionInput(document.getElementById('hist-a').value)
+            const d = parseFractionInput(document.getElementById('hist-d').value)
+            const fInputs = document.getElementById('hist-f').value.split(' ').filter(Boolean)
+            const pInput = document.getElementById('hist-p').value
+
+            // 验证输入有效性
+            if (!a || !d || fInputs.length === 0) {
+                results.innerHTML = '<p class="text-red-500">错误:请输入有效的输入值</p>'
+                return
+            }
+
+            // 转换频率为分数数组
+            const f = fInputs.map(parseFractionInput).filter(f => f !== null)
+            if (f.length !== fInputs.length) {
+                results.innerHTML = '<p class="text-red-500">错误:包含无效的频率值</p>'
+                return
+            }
+
+            // 计算频率总和
+            const sump = f.reduce((acc, val) => acc.add(val), new Fraction(0))
+            if (!sump.equals(1)) {
+                results.innerHTML = `<p class="text-red-500">错误:频率总和应为1(当前为${sump.toFraction()})</p>`
+                return
+            }
+
+            // 计算均值和方差
+            let x = d.div(2)
+            let s = new Fraction(0)
+            const n = f.length
+            
+            for (let i = 0; i < n; i++) {
+                x = x.add(a.add(d.mul(i)).mul(f[i]))
+            }
+            
+            for (let i = 0; i < n; i++) {
+                const mid = a.add(d.mul(i)).add(d.div(2))
+                s = s.add(mid.sub(x).pow(2).mul(f[i]))
+            }
+
+            // 显示基础统计量
+            let output = `
+                <div class="space-y-2">
+                    <p class="font-medium">均值 = ${x.toFraction()} ≈ ${x.valueOf().toFixed(4)}</p>
+                    <p class="font-medium">方差 = ${s.toFraction()} ≈ ${s.valueOf().toFixed(4)}</p>
+            `
+
+            // 百分位数计算
+            if (pInput) {
+                const p = parseFractionInput(pInput)
+                if (p && p.compare(0) > 0 && p.compare(1) < 0) {
+                    let m = new Fraction(0)
+                    for (let i = 0; i < n; i++) {
+                        if (m.add(f[i]).compare(p) >= 0) {
+                            const q = a.add(d.mul(i)).sub(m.sub(p).div(f[i-1]).mul(d))
+                            const integer = q.floor()
+                            const decimal = q.sub(integer)
+                            output += `<p>${p.toFraction()} 分位数 = ${integer} + ${decimal.toFraction()}</p>`
+                            break
+                        }
+                        m = m.add(f[i])
+                    }
+                }
+            }
+
+            // 中位数计算
+            let m = new Fraction(0)
+            for (let i = 0; i < n; i++) {
+                if (m.add(f[i]).compare(0.5) >= 0) {
+                    const q = a.add(d.mul(i)).sub(m.sub(0.5).div(f[i-1]).mul(d))
+                    const integer = q.floor()
+                    const decimal = q.sub(integer)
+                    output += `<p class="font-medium">中位数 = ${integer} + ${decimal.toFraction()}</p>`
+                    break
+                }
+                m = m.add(f[i])
+            }
+
+            output += '</div>'
+            results.innerHTML = output
+        }
+    </script>
+</body>
+</html>

+ 97 - 0
html小工具/等差乘等比求和计算器.html

@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>等差乘等比求和计算器</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+</head>
+<body class="min-h-screen bg-gray-100 flex items-center justify-center">
+    <div class="bg-white p-8 rounded-lg shadow-lg w-96">
+        <h1 class="text-2xl font-bold mb-6 text-gray-800">错位相减法计算器</h1>
+        
+        <div class="space-y-4">
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-1">a (系数):</label>
+                <input type="text" id="a" class="w-full border rounded px-3 py-2" placeholder="如: 3/4 或 0.75">
+            </div>
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-1">b (常数项):</label>
+                <input type="text" id="b" class="w-full border rounded px-3 py-2" placeholder="如: 1/2 或 0.5">
+            </div>
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-1">q (公比):</label>
+                <input type="text" id="q" class="w-full border rounded px-3 py-2" placeholder="如: 2 或 1/3">
+            </div>
+            <div>
+                <label class="block text-sm font-medium text-gray-700 mb-1">m (指数调整):</label>
+                <input type="text" id="m" class="w-full border rounded px-3 py-2" placeholder="整数,如: 2">
+            </div>
+        </div>
+
+        <button onclick="calculate()" class="w-full bg-blue-500 text-white py-2 px-4 rounded mt-6 hover:bg-blue-600 transition-colors">
+            计算
+        </button>
+
+        <div id="result" class="hidden mt-6 p-4 bg-gray-50 rounded">
+            <p class="font-medium text-gray-800">结果公式:Sₙ = (A⋅n + B)qⁿ - B</p>
+            <div class="mt-3 space-y-2">
+                <p class="text-sm">A = <span id="A-value" class="font-mono text-blue-600"></span></p>
+                <p class="text-sm">B = <span id="B-value" class="font-mono text-blue-600"></span></p>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        // 确保Fraction库可用性检查
+        if (typeof Fraction === 'undefined') {
+            alert('错误:分数库加载失败,请检查网络连接!');
+        }
+
+        function parseInput(value) {
+            try {
+                return new Fraction(value);
+            } catch (e) {
+                throw new Error('无效的分数格式,请使用如 3/4 或 0.75 的格式');
+            }
+        }
+
+        function calculate() {
+            try {
+                // 检查Fraction库是否加载
+                if (typeof Fraction === 'undefined') {
+                    throw new Error('分数库加载失败,请刷新页面重试');
+                }
+
+                // 解析输入值
+                const a = parseInput(document.getElementById('a').value);
+                const b = parseInput(document.getElementById('b').value);
+                const q = parseInput(document.getElementById('q').value);
+                const m = parseInt(document.getElementById('m').value);
+
+                // 验证输入有效性
+                if (isNaN(m)) throw new Error('m必须是整数');
+                if (q.valueOf() === 1) throw new Error('q不能等于1');
+
+                // 计算调整系数
+                const qPower = q.pow(m + 1);
+                const adjustedA = a.mul(qPower);
+                const adjustedB = b.mul(qPower);
+
+                // 计算核心参数
+                const qMinus1 = q.sub(1);
+                const A = adjustedA.div(qMinus1);
+                const B = adjustedB.sub(A).div(qMinus1);
+
+                // 显示结果
+                document.getElementById('result').classList.remove('hidden');
+                document.getElementById('A-value').textContent = A.toFraction();
+                document.getElementById('B-value').textContent = B.toFraction();
+                
+            } catch (error) {
+                alert(`计算错误: ${error.message}`);
+            }
+        }
+    </script>
+</body>
+</html>

+ 130 - 0
html小工具/统计计算工具.html

@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>统计计算工具</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+</head>
+<body class="p-6 bg-gray-100">
+    <div class="max-w-2xl mx-auto space-y-8">
+        <!-- 卡方计算 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">卡方计算(2×2列联表)</h2>
+            <div class="grid grid-cols-2 gap-4 mb-4">
+                <input type="number" id="a" class="p-2 border rounded" placeholder="a">
+                <input type="number" id="b" class="p-2 border rounded" placeholder="b">
+                <input type="number" id="c" class="p-2 border rounded" placeholder="c">
+                <input type="number" id="d" class="p-2 border rounded" placeholder="d">
+            </div>
+            <button onclick="calculateChiSquare()" class="w-full bg-purple-500 text-white p-2 rounded hover:bg-purple-600">
+                计算卡方值
+            </button>
+            <div id="chi2-results" class="mt-4 space-y-2"></div>
+        </div>
+
+        <!-- 线性回归计算 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">一元线性回归</h2>
+            <div class="space-y-4">
+                <div>
+                    <label class="block mb-2">X 值(空格分隔)</label>
+                    <input type="text" id="x-values" class="w-full p-2 border rounded" placeholder="例如: 1 2 3 4 5">
+                </div>
+                <div>
+                    <label class="block mb-2">Y 值(空格分隔)</label>
+                    <input type="text" id="y-values" class="w-full p-2 border rounded" placeholder="例如: 2 4 6 8 10">
+                </div>
+                <button onclick="calculateRegression()" class="w-full bg-orange-500 text-white p-2 rounded hover:bg-orange-600">
+                    计算回归参数
+                </button>
+                <div id="regression-results" class="mt-4 space-y-2"></div>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        // 卡方计算
+        function calculateChiSquare() {
+            const a = parseInt(document.getElementById('a').value) || 0;
+            const b = parseInt(document.getElementById('b').value) || 0;
+            const c = parseInt(document.getElementById('c').value) || 0;
+            const d = parseInt(document.getElementById('d').value) || 0;
+            
+            const n = a + b + c + d;
+            const numerator = n * Math.pow((a * d - b * c), 2);
+            const denominator = (a + b) * (c + d) * (a + c) * (b + d);
+            
+            const K2 = new Fraction(numerator).div(denominator);
+            const results = document.getElementById('chi2-results');
+            
+            results.innerHTML = `
+                <p class="font-medium">卡方值 K² = ${K2.toFraction()}</p>
+                <p class="font-medium">近似值 ≈ ${K2.valueOf().toFixed(4)}</p>
+            `;
+        }
+
+        // 线性回归计算
+        function calculateRegression() {
+            const xInput = document.getElementById('x-values').value.split(' ').filter(Boolean);
+            const yInput = document.getElementById('y-values').value.split(' ').filter(Boolean);
+            const results = document.getElementById('regression-results');
+            
+            if (xInput.length !== yInput.length) {
+                results.innerHTML = '<p class="text-red-500">错误:X 和 Y 的数据量不一致</p>';
+                return;
+            }
+
+            const n = xInput.length;
+            let sx = 0, sy = 0, sx2 = 0, sy2 = 0, sxy = 0;
+            
+            // 转换输入为数值
+            const x = xInput.map(Number);
+            const y = yInput.map(Number);
+
+            // 计算各项总和
+            for (let i = 0; i < n; i++) {
+                sx += x[i];
+                sy += y[i];
+                sx2 += x[i] ** 2;
+                sy2 += y[i] ** 2;
+                sxy += x[i] * y[i];
+            }
+
+            // 计算统计量
+            const xBar = sx / n;
+            const yBar = sy / n;
+            const sigmaX = sx2 - n * xBar ** 2;
+            const sigmaY = sy2 - n * yBar ** 2;
+            const sigmaXY = sxy - n * xBar * yBar;
+            const r = sigmaXY / Math.sqrt(sigmaX * sigmaY);
+            const b = sigmaXY / sigmaX;
+            const a = yBar - b * xBar;
+
+            // 计算残差平方和和决定系数
+            let se2 = 0;
+            for (let i = 0; i < n; i++) {
+                se2 += (y[i] - b * x[i] - a) ** 2;
+            }
+            const R2 = 1 - (se2 / sigmaY);
+
+            // 格式化显示结果
+            results.innerHTML = `
+                <div class="space-y-2">
+                    <p>均值 x̄ = ${xBar.toFixed(4)}</p>
+                    <p>均值 ȳ = ${yBar.toFixed(4)}</p>
+                    <p>方差 Σ(x-x̄)² = ${sigmaX.toFixed(4)}</p>
+                    <p>方差 Σ(y-ȳ)² = ${sigmaY.toFixed(4)}</p>
+                    <p>协方差 Σ(x-x̄)(y-ȳ) = ${sigmaXY.toFixed(4)}</p>
+                    <p class="font-medium">相关系数 r = ${r.toFixed(4)}</p>
+                    <p class="font-medium">回归系数 b = ${b.toFixed(4)}</p>
+                    <p class="font-medium">截距 a = ${a.toFixed(4)}</p>
+                    <p>残差平方和 = ${se2.toFixed(4)}</p>
+                    <p class="font-medium">决定系数 R² = ${R2.toFixed(4)}</p>
+                </div>
+            `;
+        }
+    </script>
+</body>
+</html>

+ 273 - 0
html小工具/解析几何计算工具.html

@@ -0,0 +1,273 @@
+<!DOCTYPE html>
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>几何计算工具</title>
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.jsdelivr.net/npm/fraction.js@4.2.0/fraction.min.js"></script>
+</head>
+<body class="p-6 bg-gray-100">
+    <div class="max-w-2xl mx-auto space-y-8">
+        <!-- 点关于直线对称 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">点关于直线对称</h2>
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block mb-2">点坐标 (x,y)</label>
+                    <input type="text" id="pl-x" class="w-full p-2 border rounded" placeholder="x">
+                    <input type="text" id="pl-y" class="w-full p-2 border rounded mt-2" placeholder="y">
+                </div>
+                <div>
+                    <label class="block mb-2">直线方程 Ax+By+C=0</label>
+                    <input type="text" id="pl-A" class="w-full p-2 border rounded" placeholder="A">
+                    <input type="text" id="pl-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                    <input type="text" id="pl-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                </div>
+            </div>
+            <button onclick="calcPointLineSymmetry()" class="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 mt-4">
+                计算对称点
+            </button>
+            <div id="pl-result" class="mt-4 space-y-2"></div>
+        </div>
+
+        <!-- 直线关于点对称 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">直线关于点对称</h2>
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block mb-2">直线方程 Ax+By+C=0</label>
+                    <input type="text" id="lp-A" class="w-full p-2 border rounded" placeholder="A">
+                    <input type="text" id="lp-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                    <input type="text" id="lp-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                </div>
+                <div>
+                    <label class="block mb-2">对称点 (x,y)</label>
+                    <input type="text" id="lp-x" class="w-full p-2 border rounded" placeholder="x">
+                    <input type="text" id="lp-y" class="w-full p-2 border rounded mt-2" placeholder="y">
+                </div>
+            </div>
+            <button onclick="calcLinePointSymmetry()" class="w-full bg-green-500 text-white p-2 rounded hover:bg-green-600 mt-4">
+                计算对称直线
+            </button>
+            <div id="lp-result" class="mt-4 space-y-2"></div>
+        </div>
+
+        <!-- 直线关于直线对称 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">直线关于直线对称</h2>
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block mb-2">原直线 Px+Qy+R=0</label>
+                    <input type="text" id="ll-P" class="w-full p-2 border rounded" placeholder="P">
+                    <input type="text" id="ll-Q" class="w-full p-2 border rounded mt-2" placeholder="Q">
+                    <input type="text" id="ll-R" class="w-full p-2 border rounded mt-2" placeholder="R">
+                </div>
+                <div>
+                    <label class="block mb-2">对称轴 Ax+By+C=0</label>
+                    <input type="text" id="ll-A" class="w-full p-2 border rounded" placeholder="A">
+                    <input type="text" id="ll-B" class="w-full p-2 border rounded mt-2" placeholder="B">
+                    <input type="text" id="ll-C" class="w-full p-2 border rounded mt-2" placeholder="C">
+                </div>
+            </div>
+            <button onclick="calcLineLineSymmetry()" class="w-full bg-purple-500 text-white p-2 rounded hover:bg-purple-600 mt-4">
+                计算对称直线
+            </button>
+            <div id="ll-result" class="mt-4 space-y-2"></div>
+        </div>
+
+        <!-- 三点求圆 -->
+        <div class="bg-white rounded-lg shadow-md p-6">
+            <h2 class="text-xl font-bold mb-4">三点确定圆的方程</h2>
+            <div class="grid grid-cols-3 gap-4">
+                <div>
+                    <label class="block mb-2">点1 (x,y)</label>
+                    <input type="text" id="c-x1" class="w-full p-2 border rounded" placeholder="x1">
+                    <input type="text" id="c-y1" class="w-full p-2 border rounded mt-2" placeholder="y1">
+                </div>
+                <div>
+                    <label class="block mb-2">点2 (x,y)</label>
+                    <input type="text" id="c-x2" class="w-full p-2 border rounded" placeholder="x2">
+                    <input type="text" id="c-y2" class="w-full p-2 border rounded mt-2" placeholder="y2">
+                </div>
+                <div>
+                    <label class="block mb-2">点3 (x,y)</label>
+                    <input type="text" id="c-x3" class="w-full p-2 border rounded" placeholder="x3">
+                    <input type="text" id="c-y3" class="w-full p-2 border rounded mt-2" placeholder="y3">
+                </div>
+            </div>
+            <button onclick="calcCircle()" class="w-full bg-orange-500 text-white p-2 rounded hover:bg-orange-600 mt-4">
+                计算圆方程
+            </button>
+            <div id="c-result" class="mt-4 space-y-2"></div>
+        </div>
+    </div>
+
+    <script>
+        // 公共函数:解析分数输入
+        function parseFraction(input) {
+            try {
+                if (input.includes('/')) {
+                    const [numerator, denominator] = input.split('/').map(Number)
+                    return new Fraction(numerator, denominator)
+                }
+                return new Fraction(parseFloat(input))
+            } catch {
+                return null
+            }
+        }
+
+        // 二阶行列式计算
+        function det2(a, b, c, d) {
+            return a.mul(d).sub(b.mul(c))
+        }
+
+        // 解二元一次方程组
+        function solveSystem(a1, b1, c1, a2, b2, c2) {
+            const D = det2(a1, b1, a2, b2)
+            if (D.valueOf() === 0) return [null, null]
+            const Dx = det2(c1, b1, c2, b2)
+            const Dy = det2(a1, c1, a2, c2)
+            return [Dx.div(D), Dy.div(D)]
+        }
+
+        // 点关于直线对称
+        // 点关于直线对称
+function calcPointLineSymmetry() {
+    const result = document.getElementById('pl-result')
+    result.innerHTML = ''
+
+    // 解析输入
+    const x = parseFraction(document.getElementById('pl-x').value)
+    const y = parseFraction(document.getElementById('pl-y').value)
+    const A = parseFraction(document.getElementById('pl-A').value)
+    const B = parseFraction(document.getElementById('pl-B').value)
+    const C = parseFraction(document.getElementById('pl-C').value)
+
+    if (!x || !y || !A || !B || !C) {
+        result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+        return
+    }
+
+    // 构造方程组(修复方程构造)
+    const equation1 = A.mul(x).add(B.mul(y)).add(C.mul(2)).neg() // 正确构造方程右侧
+    const equation2 = B.mul(x).sub(A.mul(y)) 
+
+    const [m, n] = solveSystem(
+        A, B, equation1,       // 第一个方程: A*m + B*n = -(Ax + By + 2C)
+        B, A.mul(-1), equation2 // 第二个方程: B*m - A*n = Bx - Ay
+    )
+
+    if (m && n) {
+        result.innerHTML = `
+            <p class="font-medium">对称点坐标:</p>
+            <p>(${m.toFraction()}, ${n.toFraction()})</p>
+            <p>近似值: (${m.valueOf().toFixed(2)}, ${n.valueOf().toFixed(2)})</p>
+        `
+    } else {
+        result.innerHTML = '<p class="text-red-500">错误:无法求解,可能直线不存在对称点</p>'
+    }
+}
+
+        // 直线关于点对称
+        function calcLinePointSymmetry() {
+            const result = document.getElementById('lp-result')
+            result.innerHTML = ''
+
+            const A = parseFraction(document.getElementById('lp-A').value)
+            const B = parseFraction(document.getElementById('lp-B').value)
+            const C = parseFraction(document.getElementById('lp-C').value)
+            const x = parseFraction(document.getElementById('lp-x').value)
+            const y = parseFraction(document.getElementById('lp-y').value)
+
+            if (!A || !B || !C || !x || !y) {
+                result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+                return
+            }
+
+            const m = A.mul(-2).mul(x).sub(B.mul(2).mul(y)).sub(C)
+            
+            result.innerHTML = `
+                <p class="font-medium">对称直线方程:</p>
+                <p>${A.toFraction()}x + ${B.toFraction()}y + ${m.toFraction()} = 0</p>
+                <p>近似值: ${A.valueOf().toFixed(2)}x + ${B.valueOf().toFixed(2)}y + ${m.valueOf().toFixed(2)} = 0</p>
+            `
+        }
+
+        // 直线关于直线对称
+        function calcLineLineSymmetry() {
+            const result = document.getElementById('ll-result')
+            result.innerHTML = ''
+
+            const P = parseFraction(document.getElementById('ll-P').value)
+            const Q = parseFraction(document.getElementById('ll-Q').value)
+            const R = parseFraction(document.getElementById('ll-R').value)
+            const A = parseFraction(document.getElementById('ll-A').value)
+            const B = parseFraction(document.getElementById('ll-B').value)
+            const C = parseFraction(document.getElementById('ll-C').value)
+
+            if (!P || !Q || !R || !A || !B || !C) {
+                result.innerHTML = '<p class="text-red-500">错误:请输入有效的数值</p>'
+                return
+            }
+
+            const k = P.mul(A).add(Q.mul(B)).mul(2).div(A.pow(2).add(B.pow(2)))
+            const newP = P.sub(A.mul(k))
+            const newQ = Q.sub(B.mul(k))
+            const newR = R.sub(C.mul(k))
+
+            result.innerHTML = `
+                <p class="font-medium">对称直线方程:</p>
+                <p>${newP.toFraction()}x + ${newQ.toFraction()}y + ${newR.toFraction()} = 0</p>
+                <p>近似值: ${newP.valueOf().toFixed(2)}x + ${newQ.valueOf().toFixed(2)}y + ${newR.valueOf().toFixed(2)} = 0</p>
+            `
+        }
+
+        // 三点确定圆
+        function calcCircle() {
+            const result = document.getElementById('c-result')
+            result.innerHTML = ''
+
+            // 解析三个点坐标
+            const x1 = parseFraction(document.getElementById('c-x1').value)
+            const y1 = parseFraction(document.getElementById('c-y1').value)
+            const x2 = parseFraction(document.getElementById('c-x2').value)
+            const y2 = parseFraction(document.getElementById('c-y2').value)
+            const x3 = parseFraction(document.getElementById('c-x3').value)
+            const y3 = parseFraction(document.getElementById('c-y3').value)
+
+            if (!x1 || !y1 || !x2 || !y2 || !x3 || !y3) {
+                result.innerHTML = '<p class="text-red-500">错误:请输入有效的坐标值</p>'
+                return
+            }
+
+            // 构造方程组
+            const z1 = x1.pow(2).add(y1.pow(2))
+            const z2 = x2.pow(2).add(y2.pow(2))
+            const z3 = x3.pow(2).add(y3.pow(2))
+
+            const [D, E] = solveSystem(
+                x1.sub(x2), y1.sub(y2), z2.sub(z1),
+                x1.sub(x3), y1.sub(y3), z3.sub(z1)
+            )
+
+            if (!D || !E) {
+                result.innerHTML = '<p class="text-red-500">错误:三点共线或无法形成圆</p>'
+                return
+            }
+
+            const F = z1.neg().sub(D.mul(x1)).sub(E.mul(y1))
+            const r2 = D.pow(2).add(E.pow(2)).sub(F.mul(4)).div(4)
+
+            result.innerHTML = `
+                <div class="space-y-2">
+                    <p class="font-medium">圆方程参数:</p>
+                    <p>D = ${D.toFraction()}, E = ${E.toFraction()}, F = ${F.toFraction()}</p>
+                    <p>圆心坐标: (-${D.div(2).toFraction()}, -${E.div(2).toFraction()})</p>
+                    <p>半径平方: ${r2.toFraction()} ≈ ${r2.valueOf().toFixed(4)}</p>
+                </div>
+            `
+        }
+    </script>
+</body>
+</html>

+ 12 - 0
hypergeometric.py

@@ -0,0 +1,12 @@
+#超几何分布
+from fractions import Fraction
+from math import comb
+N=11 #总数
+M=2  #次品数
+n=3  #抽取数
+m=max(0,n-N+M)
+r=min(n,M)
+print("EX=",Fraction(n*M,N))
+print("DX=",Fraction(n*M*(N-M)*(N-n),N*N*(N-1)))
+for k in range(m,r+1):
+    print("P(X=",k,")=",Fraction(comb(M,k)*comb(N-M,n-k),comb(N,n)))

+ 263 - 0
mathCheat.py

@@ -0,0 +1,263 @@
+#出现问题conda activate base
+
+import sys
+
+#等差乘等比——错位相减法
+def cuoWeiXiangJian():
+   from fractions import Fraction
+   print("错位相减法求前n项和,若通项为a_n=(a*n+b)*q^(n+m),请填写")
+   a=Fraction(input("a="))
+   b=Fraction(input("b="))
+   q=Fraction(input("q="))
+   m=int(input("m="))
+
+   #将指数统一为n-1
+   a=a*pow(q,(m+1))
+   b=b*pow(q,(m+1))
+
+   #计算A,B
+   A=a/(q-1)
+   B=(b-A)/(q-1)
+   print("结果为S_n=(An+B)*q^n-B")
+   print("A=",A, "B=",B)
+
+#二项分布
+def binomial():
+    from fractions import Fraction
+    from math import comb
+    n=int(input("n="))
+    p=Fraction(input("p="))
+    print("EX=",n*p)
+    print("DX=",n*p*(1-p))
+    for i in range(n+1):
+        print("P(X=",i,")=",comb(n,i)*pow(p,i)*pow(1-p,n-i))
+
+
+#超几何分布
+def hypergeometric():   
+    from fractions import Fraction
+    from math import comb
+    N=int(input("总数N=")) #总数
+    M=int(input("满足条件数M="))  #次品数
+    n=int(input("抽取数n="))  #抽取数
+    m=max(0,n-N+M)
+    r=min(n,M)
+    print("EX=",Fraction(n*M,N))
+    print("DX=",Fraction(n*M*(N-M)*(N-n),N*N*(N-1)))
+    for k in range(m,r+1):
+        print("P(X=",k,")=",Fraction(comb(M,k)*comb(N-M,n-k),comb(N,n)))
+
+#卡方计算
+def k2():
+    from fractions import Fraction
+    print("请输入核心2✖️2单元的abcd")
+    a=int(input("a="))
+    b=int(input("b="))
+    c=int(input("c="))
+    d=int(input("d="))
+    n=a+b+c+d
+    K2=Fraction(n*((a*d-b*c)**2),(a+b)*(c+d)*(a+c)*(b+d))
+    print("K^2=",K2)
+    print("近似值为",float(K2))
+
+#一元线性回归模型
+def regression():
+    from math import sqrt
+    x = input("请输入x(用空格分割):").split()
+    x = list(map(float,x))
+    y = input("请输入y(用空格分割):").split()
+    y = list(map(float,y))
+    sx=0
+    sy=0
+    sx2=0
+    sy2=0
+    sxy=0
+    if len(x)==len(y):
+        n = len(x)
+        for i in range(n):
+            sx += x[i]
+            sy += y[i]
+            sx2 += x[i]**2
+            sy2 += y[i]**2
+            sxy += x[i]*y[i]
+        xBar = sx/n
+        yBar = sy/n
+        sigmaX = sx2 - n*xBar*xBar
+        sigmaY = sy2 - n*yBar*yBar
+        sigmaXY = sxy - n*xBar*yBar
+        r = sigmaXY/sqrt(sigmaX*sigmaY)
+        b = sigmaXY/sigmaX
+        a = yBar-b*xBar
+
+        se2=0
+        for i in range(n):
+            se2 += (y[i]-b*x[i]-a)**2
+        R2 = 1 - se2/sigmaY
+        print("x_bar=",xBar)
+        print("y_bar=",yBar)
+        print("sigma (x-x)^2 =",sigmaX)
+        print("sigma (y-y)^2 =",sigmaY)
+        print("sigma (x-x)(y-y) =",sigmaXY)
+        print("相关系数r=",r)
+        print("b=",b)
+        print("a=",a)
+        print("残差平方和为",se2)
+        print("决定系数R^2=",R2)
+
+    else:
+        print("x,y长度不一致")
+
+
+#混合方差
+def mixS2():
+    from fractions import Fraction
+    x = input("请输入各层样本量(用空格分割):").split()
+    x = list(map(Fraction,x))
+    y = input("请输入各层对应的均值(用空格分割):").split()
+    y = list(map(Fraction,y))
+    z = input("请输入各层对应的方差(用空格分割):").split()
+    z = list(map(Fraction,z))
+    if ((len(x)==len(y))&(len(x)==len(z))):
+        m = 0
+        j = 0
+        f = 0
+        for i in range(len(x)):
+            m += x[i]
+            j += x[i]*y[i]
+        j = j/m
+        for i in range(len(x)):
+            f += x[i]*(z[i]+(y[i]-j)**2)/m
+        print("总均值为",j)
+        print("总方差为",f)
+
+    else:
+        print("输入有误!")
+
+#直方图
+def histogram():
+    from fractions import Fraction
+    from math import floor
+    a = Fraction(input("请输入直方图左端点:"))
+    d = Fraction(input("请输入直方图组距:"))
+    f = input("请输入各组频率(用空格分割):").split()
+    f = list(map(Fraction,f))
+    p = input("请输入需求解的百分位数,无需求解请留空:")
+    x = d/2
+    s = 0
+    n = len(f)
+    sump = 0
+    for pi in f:
+        sump += pi
+    if sump == 1:
+        for i in range(n):
+            x += (a+i*d)*f[i]
+        for i in range(n):
+            s += (a+i*d+d/2-x)**2*f[i]
+        print("均值:",Fraction(x),",近似值:",float(x))
+        print("方差:",Fraction(s),",近似值:",float(s))
+        m = 0
+        if p!="":
+            p = Fraction(p)
+            for i in range(n):
+                if m >= p:
+                    q = Fraction(a+i*d-(m-p)/f[i-1]*d)
+                    print(p,"百分位数为",floor(q),"+",q-floor(q))
+                    break
+                else:
+                    m += f[i]
+        m = 0
+        for i in range(n):
+            if m >= 0.5:
+                q = Fraction(a+i*d-(m-0.5)/f[i-1]*d)
+                print("中位数为",floor(q),"+",q-floor(q))
+                break
+            else:
+                m += f[i]
+    else:
+        print("频率之和不为1")
+
+#二阶行列式
+def det2(a,b,c,d):
+    return a*d-b*c
+
+#二元一次方程组
+def tle(a1,b1,c1,a2,b2,c2):
+    return((det2(c1,b1,c2,b2)/det2(a1,b1,a2,b2),det2(a1,c1,a2,c2)/det2(a1,b1,a2,b2)))
+
+#点关于直线对称
+def dot_line():
+    from fractions import Fraction
+    a=Fraction(input("请输入点的横坐标:"))
+    b=Fraction(input("请输入点的纵坐标:"))
+    A=Fraction(input("请输入直线一般方程x的系数:"))
+    B=Fraction(input("请输入直线一般方程y的系数:"))
+    C=Fraction(input("请输入直线一般方程的常数项:"))
+    m,n = tle(A,B,(-1)*(A*a+B*b+2*C),B,-A,a*B-A*b)
+    print("对称点为:(",m,",",n,")")
+
+#直线关于点对称
+def line_dot():
+    from fractions import Fraction 
+    A=Fraction(input("请输入直线一般方程x的系数:"))
+    B=Fraction(input("请输入直线一般方程y的系数:"))
+    C=Fraction(input("请输入直线一般方程的常数项:"))
+    a=Fraction(input("请输入点的横坐标:"))
+    b=Fraction(input("请输入点的纵坐标:"))
+    m=-2*A*a-2*B*b-C
+    print("对称直线三个系数分别为:",A,B,m)
+
+#直线关于直线对称
+def line_line():
+    from fractions import Fraction 
+    P=Fraction(input("请输入直线一般方程x的系数:"))
+    Q=Fraction(input("请输入直线一般方程y的系数:"))
+    R=Fraction(input("请输入直线一般方程的常数项:"))
+    A=Fraction(input("请输入对称轴一般方程x的系数:"))
+    B=Fraction(input("请输入对称轴一般方程y的系数:"))
+    C=Fraction(input("请输入对称轴一般方程的常数项:"))
+    k=2*(P*A+Q*B)/(A*A+B*B)
+    print("对称直线三个系数分别为:",P-A*k,Q-B*k,R-C*k)
+
+#三个点求圆的方程
+def circle():
+    from fractions import Fraction
+    x1=Fraction(input("请输入第一个点的横坐标:"))
+    y1=Fraction(input("请输入第一个点的纵坐标:"))
+    x2=Fraction(input("请输入第二个点的横坐标:"))
+    y2=Fraction(input("请输入第二个点的纵坐标:"))
+    x3=Fraction(input("请输入第三个点的横坐标:"))
+    y3=Fraction(input("请输入第三个点的纵坐标:"))
+    z1=x1*x1+y1*y1
+    z2=x2*x2+y2*y2
+    z3=x3*x3+y3*y3
+    D,E = tle(x1-x2,y1-y2,z2-z1,x1-x3,y1-y3,z3-z1)
+    F = -z1-D*x1-E*y1
+    r2 = D*D+E*E-4*F
+    print("D=",D,"E=",E,"F=",F)
+    print("圆心:(",-D/2,",",-E/2,")"," 半径的平方:",r2)
+
+def main():
+    if len(sys.argv) < 2:
+        print("Usage: python mathCheat.py <tool_name>")
+        sys.exit(1)
+
+    tool_name = sys.argv[1]
+
+    if tool_name in toolbox:
+      try:
+         toolbox[tool_name]()
+      except:
+         print("某些地方出错了!")
+    else:
+        print("工具名无效!")
+        sys.exit(1)
+
+if __name__ == "__main__":
+    toolbox = {"错位相减":cuoWeiXiangJian,"错位相减法":cuoWeiXiangJian, "等差乘等比":cuoWeiXiangJian,
+"二项分布":binomial,"超几何分布":hypergeometric,"K2":k2,"卡方":k2,"独立性检验":k2,
+"回归分析":regression,"相关系数":regression,"最小二乘法":regression,"决定系数":regression,"残差平方和":regression,"线性回归":regression,
+"混合方差":mixS2,"混合均值":mixS2,"直方图":histogram,
+"点关于线对称":dot_line, "点关于直线对称":dot_line,  "直线关于点对称":line_dot, "线关于点对称":line_dot,  "直线关于直线对称":line_line, "线关于线对称":line_line,
+"三个点求圆的方程":circle,"已知三点求圆的方程":circle,"求圆的方程":circle,           
+               }
+    main()

+ 23 - 0
orgnazieFolder.sh

@@ -0,0 +1,23 @@
+#!/bin/bash
+#按照后缀名整理目标文件夹,默认为Downloads文件夹
+
+# 检查是否传入了目标文件夹参数
+if [ -z "$1" ]
+then
+    # 如果没有传入目标文件夹参数,则默认为Downloads文件夹
+    target_folder="$HOME/Downloads"
+else
+    # 如果传入了目标文件夹参数,则使用该参数作为目标文件夹
+    target_folder="$1"
+fi
+
+
+# 进入要整理的文件夹
+cd "$target_folder"
+
+# 根据文件扩展名整理文件
+for file in *; do
+  if [ -f "$file" ]; then
+      mv "$file" "../${file%.*}"
+  fi
+done

+ 19 - 0
processTxt.py

@@ -0,0 +1,19 @@
+#出现问题conda activate base
+#将文本的前19万字符留下
+import sys
+
+def main():
+    input_file = sys.argv[1]  # 输入文件名
+    output_file = sys.argv[1] + "out.txt" # 输出文件名
+    chars_to_keep = 190000  # 需要保留的字符数
+
+    with open(input_file, 'r', encoding='utf-8') as f_in, open(output_file, 'w', encoding='utf-8') as f_out:
+       count = 0
+       for line in f_in:
+           count += len(line)
+           if count > chars_to_keep:
+               break
+           f_out.write(line)
+
+if __name__ == "__main__":
+   main()

+ 767 - 0
rationalsqrt2.dart

@@ -0,0 +1,767 @@
+/* 此文件实现了有理数与二次根式形成的数域
+ * 需要在pubspec.yaml中添加依赖rational: ^2.2.3
+ * 使用方法请看最后的测试用例
+ * Ksqrt类表示有理数乘以根号整数
+ * RationalExtend类表示多个Ksqrt类根式相加
+ * Author:nonvioce
+ * Time: 2025.10.26
+*/
+import 'package:rational/rational.dart';
+import 'dart:math';
+
+class Ksqrt {
+  Rational k; // 有理数系数
+  int q;      // 底数(整数)
+
+  Ksqrt(this.k, this.q) {
+    if (q < 0) throw ArgumentError("底数q不能为负数");
+  }
+
+  // 从整数创建(系数为整数,底数为1)
+  factory Ksqrt.fromInt(int value) {
+    return Ksqrt(Rational.fromInt(value), 1);
+  }
+
+  // 从Rational创建(系数为有理数,底数为1)
+  factory Ksqrt.fromRational(Rational rational) {
+    return Ksqrt(rational, 1);
+  }
+
+  // 增强的字符串解析 - 增加小数支持
+  factory Ksqrt.parse(String str) {
+    str = str.trim();
+
+    // 处理纯数字(整数或小数)
+    if (RegExp(r'^-?\d+(\.\d+)?$').hasMatch(str)) {
+      return Ksqrt.fromRational(_parseRational(str));
+    }
+
+    // 处理分数(不包含根号)
+    if (str.contains('/') && !str.contains('√')) {
+      try {
+        var parts = str.split('/');
+        if (parts.length != 2) throw FormatException("无效的分数格式: $str");
+
+        var numerator = _parseRational(parts[0]);
+        var denominator = _parseRational(parts[1]);
+
+        if (denominator == Rational.zero) throw FormatException("分母不能为零: $str");
+
+        return Ksqrt.fromRational(numerator / denominator);
+      } catch (e) {
+        throw FormatException("无效的分数格式: $str, 错误: $e");
+      }
+    }
+
+    // 处理根式
+    if (str.contains('√')) {
+      var sqrtIndex = str.indexOf('√');
+      var coefficientStr = str.substring(0, sqrtIndex);
+      var radicandStr = str.substring(sqrtIndex + 1);
+
+      // 处理括号内的底数
+      if (radicandStr.startsWith('(') && radicandStr.endsWith(')')) {
+        radicandStr = radicandStr.substring(1, radicandStr.length - 1);
+      }
+
+      Rational k;
+
+      // 解析系数
+      if (coefficientStr.isEmpty || coefficientStr == "+") {
+        k = Rational.one;
+      } else if (coefficientStr == "-") {
+        k = -Rational.one;
+      } else {
+        coefficientStr = coefficientStr.replaceAll('*', '');
+        try {
+          if (coefficientStr.contains('/')) {
+            var coeffParts = coefficientStr.split('/');
+            if (coeffParts.length != 2) throw FormatException("无效的系数格式: $coefficientStr");
+
+            var num = _parseRational(coeffParts[0]);
+            var den = _parseRational(coeffParts[1]);
+            if (den == Rational.zero) throw FormatException("分母不能为零: $coefficientStr");
+
+            k = num / den;
+          } else {
+            k = _parseRational(coefficientStr);
+          }
+        } catch (e) {
+          throw FormatException("无效的系数格式: $coefficientStr");
+        }
+      }
+
+      // 解析底数
+      int q;
+      if (radicandStr.contains('/')) {
+        throw FormatException("分数底数暂不支持: $str");
+      } else {
+        try {
+          // 底数必须是整数,所以使用int.parse而不是_parseRational
+          q = int.parse(radicandStr);
+        } catch (e) {
+          throw FormatException("无效的底数格式: $radicandStr");
+        }
+      }
+
+      return Ksqrt(k, q)..simplify();
+    }
+
+    // 尝试解析为有理数(包括小数)
+    try {
+      return Ksqrt.fromRational(_parseRational(str));
+    } catch (e) {
+      throw FormatException("无法解析的字符串: $str");
+    }
+  }
+
+  // 小数转有理数的辅助函数
+  static Rational _parseRational(String input) {
+    try {
+      input = input.trim();
+
+      if (input.contains('/')) {
+        List<String> parts = input.split('/');
+        if (parts.length == 2) {
+          String numerator = parts[0].trim();
+          String denominator = parts[1].trim();
+
+          // 修复:直接使用 Rational 构造函数而不是 parse
+          BigInt num = BigInt.parse(numerator);
+          BigInt den = BigInt.parse(denominator);
+
+          if (den == BigInt.zero) {
+            throw FormatException('分母不能为零');
+          }
+
+          return Rational(num, den);
+        }
+      }
+
+      // 处理小数
+      if (input.contains('.')) {
+        return _decimalToRational(input);
+      }
+
+      // 处理整数
+      return Rational.parse(input);
+    } catch (e) {
+      throw FormatException('无效的分数格式: $input');
+    }
+  }
+
+  // 小数转有理数的实现
+  static Rational _decimalToRational(String decimalStr) {
+    if (!decimalStr.contains('.')) {
+      return Rational.parse(decimalStr);
+    }
+
+    List<String> parts = decimalStr.split('.');
+    String integerPart = parts[0];
+    String decimalPart = parts[1];
+
+    // 处理负号
+    bool isNegative = integerPart.startsWith('-');
+    if (isNegative) {
+      integerPart = integerPart.substring(1);
+    }
+
+    // 如果整数部分是空的,设为0
+    if (integerPart.isEmpty) {
+      integerPart = '0';
+    }
+
+    // 计算分母:10的decimalPart长度次方
+    BigInt denominator = BigInt.from(10).pow(decimalPart.length);
+    // 计算分子:整数部分 * 分母 + 小数部分
+    BigInt numerator =
+    BigInt.parse(integerPart) * denominator + BigInt.parse(decimalPart);
+
+    if (isNegative) {
+      numerator = -numerator;
+    }
+
+    return Rational(numerator, denominator);
+  }
+
+  // 取反运算
+  Ksqrt operator -() {
+    return Ksqrt(-k, q);
+  }
+
+  // 修复的化简方法
+  void simplify() {
+    if (k == Rational.zero) {
+      q = 1;
+      return;
+    }
+
+    if (q == 0 || q == 1) return;
+
+    // 提取平方因子
+    int squareFactor = 1;
+    int temp = q;
+
+    for (int i = 2; i * i <= temp; i++) {
+      while (temp % (i * i) == 0) {
+        squareFactor *= i;
+        temp ~/= (i * i);
+      }
+    }
+
+    // 更新系数和底数
+    if (squareFactor > 1) {
+      k *= Rational.fromInt(squareFactor);
+      q = temp;
+    }
+  }
+
+  // 判断两个Ksqrt是否同类项
+  bool isLikeTerm(Ksqrt other) {
+    Ksqrt thisCopy = Ksqrt(k, q);
+    Ksqrt otherCopy = Ksqrt(other.k, other.q);
+    thisCopy.simplify();
+    otherCopy.simplify();
+    return thisCopy.q == otherCopy.q;
+  }
+
+  // 加法运算
+  Ksqrt operator +(Ksqrt other) {
+    if (!isLikeTerm(other)) {
+      throw ArgumentError("底数不同无法相加: ${this.q} 和 ${other.q}");
+    }
+
+    Ksqrt thisCopy = Ksqrt(k, q);
+    Ksqrt otherCopy = Ksqrt(other.k, other.q);
+    thisCopy.simplify();
+    otherCopy.simplify();
+
+    return Ksqrt(thisCopy.k + otherCopy.k, thisCopy.q);
+  }
+
+  // 减法运算
+  Ksqrt operator -(Ksqrt other) {
+    if (!isLikeTerm(other)) {
+      throw ArgumentError("底数不同无法相减: ${this.q} 和 ${other.q}");
+    }
+
+    Ksqrt thisCopy = Ksqrt(k, q);
+    Ksqrt otherCopy = Ksqrt(other.k, other.q);
+    thisCopy.simplify();
+    otherCopy.simplify();
+
+    return Ksqrt(thisCopy.k - otherCopy.k, thisCopy.q);
+  }
+
+  // 乘法运算
+  Ksqrt operator *(Ksqrt other) {
+    Rational newK = k * other.k;
+    int newQ = q * other.q;
+
+    Ksqrt result = Ksqrt(newK, newQ);
+    result.simplify();
+    return result;
+  }
+
+  // 修复的除法运算
+  Ksqrt operator /(Ksqrt other) {
+    if (other.k == Rational.zero) {
+      throw ArgumentError("除数不能为零");
+    }
+
+    // 分子分母同乘以分母的根号部分进行有理化
+    Rational newK = k * other.k;
+    int newQ = q * other.q;
+
+    // 除以分母系数的平方(因为分母是k√q,有理化后分母变为k²q)
+    Rational denominator = other.k * other.k * Rational.fromInt(other.q);
+
+    Ksqrt result = Ksqrt(newK / denominator, newQ);
+    result.simplify();
+    return result;
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (other is! Ksqrt) return false;
+
+    Ksqrt thisSimplified = Ksqrt(k, q)..simplify();
+    Ksqrt otherSimplified = Ksqrt(other.k, other.q)..simplify();
+
+    return thisSimplified.k == otherSimplified.k &&
+    thisSimplified.q == otherSimplified.q;
+  }
+
+  @override
+  int get hashCode {
+    Ksqrt simplified = Ksqrt(k, q)..simplify();
+    return Object.hash(simplified.k, simplified.q);
+  }
+
+  // 计算表达式的近似浮点数值
+  double toDouble() {
+    if (k == Rational.zero) return 0.0;
+
+    double sqrtQ = sqrt(q.toDouble());
+    double kValue = k.toDouble();
+
+    return kValue * sqrtQ;
+  }
+
+  @override
+  String toString() {
+    if (k == Rational.zero) return '0';
+    if (q == 1) return k.toString();
+
+    String kStr;
+    if (k == Rational.one) {
+      kStr = '';
+    } else if (k == -Rational.one) {
+      kStr = '-';
+    } else {
+      if (k.isInteger) {
+        kStr = k.toDouble().toInt().toString();
+      } else {
+        kStr = '($k)';
+      }
+      kStr += '*';
+    }
+
+    return '${kStr}√$q';
+  }
+}
+
+class RationalExtend {
+  List<Ksqrt> terms;
+
+  RationalExtend(this.terms);
+
+  factory RationalExtend.fromInt(int value) {
+    return RationalExtend([Ksqrt.fromInt(value)]);
+  }
+
+  factory RationalExtend.fromRational(Rational rational) {
+    return RationalExtend([Ksqrt.fromRational(rational)]);
+  }
+
+  // 改进的字符串解析 - 现在支持小数
+  factory RationalExtend.parse(String str) {
+    str = str.replaceAll(' ', '');
+
+    if (str.isEmpty) return RationalExtend([]);
+
+    // 处理单个项的情况
+    if (!str.contains('+') && !str.contains('-')) {
+      return RationalExtend([Ksqrt.parse(str)]);
+    }
+
+    // 处理以负号开头的情况
+    if (str.startsWith('-')) {
+      var rest = str.substring(1);
+      if (!rest.contains('+') && !rest.contains('-')) {
+        return RationalExtend([Ksqrt.parse(str)]);
+      }
+    }
+
+    List<Ksqrt> terms = [];
+    List<String> termStrs = [];
+
+    // 改进的分割逻辑:正确处理符号
+    int start = 0;
+    for (int i = 1; i < str.length; i++) {
+      if ((str[i] == '+' || str[i] == '-') &&
+        str[i-1] != '*' && str[i-1] != '/' && str[i-1] != '^') {
+        termStrs.add(str.substring(start, i));
+      start = i;
+        }
+    }
+    termStrs.add(str.substring(start));
+
+    // 解析各项
+    for (var termStr in termStrs) {
+      if (termStr.isEmpty) continue;
+      if (termStr == '+') continue;
+
+      try {
+        terms.add(Ksqrt.parse(termStr));
+      } catch (e) {
+        throw FormatException("无法解析项: $termStr, 错误: $e");
+      }
+    }
+
+    return RationalExtend(terms)..simplify();
+  }
+
+  void addTerm(Ksqrt term) {
+    terms.add(term);
+  }
+
+  // 化简方法:合并同类项
+  void simplify() {
+    if (terms.isEmpty) return;
+
+    // 首先对每个项进行化简
+    for (var term in terms) {
+      term.simplify();
+    }
+
+    // 合并同类项
+    Map<int, Rational> termMap = {};
+
+    for (var term in terms) {
+      if (termMap.containsKey(term.q)) {
+        termMap[term.q] = termMap[term.q]! + term.k;
+      } else {
+        termMap[term.q] = term.k;
+      }
+    }
+
+    // 重建terms列表
+    terms.clear();
+    termMap.forEach((q, k) {
+      if (k != Rational.zero) {
+        terms.add(Ksqrt(k, q));
+      }
+    });
+
+    // 按底数排序
+    terms.sort((a, b) => a.q.compareTo(b.q));
+
+    if (terms.isEmpty) {
+      terms.add(Ksqrt.fromInt(0));
+    }
+  }
+
+  // 获取共轭表达式
+  RationalExtend get conjugate {
+    if (terms.length == 1) {
+      return RationalExtend([terms[0]]);
+    } else if (terms.length == 2) {
+      return RationalExtend([
+        terms[0],
+        Ksqrt(-terms[1].k, terms[1].q)
+      ]);
+    } else {
+      List<Ksqrt> conjugateTerms = [terms[0]];
+      for (int i = 1; i < terms.length; i++) {
+        conjugateTerms.add(Ksqrt(-terms[i].k, terms[i].q));
+      }
+      return RationalExtend(conjugateTerms);
+    }
+  }
+
+  // 检查是否是有理数
+  bool get isRational {
+    for (var term in terms) {
+      if (term.q != 1) return false;
+    }
+    return true;
+  }
+
+  // 获取有理数部分的值
+  Rational get rationalValue {
+    if (!isRational) {
+      throw StateError("表达式包含根号,不是纯有理数");
+    }
+
+    Rational sum = Rational.zero;
+    for (var term in terms) {
+      sum += term.k;
+    }
+    return sum;
+  }
+
+  // 加法运算
+  RationalExtend operator +(RationalExtend other) {
+    List<Ksqrt> newTerms = List.from(terms);
+    newTerms.addAll(other.terms);
+
+    RationalExtend result = RationalExtend(newTerms);
+    result.simplify();
+    return result;
+  }
+
+  // 减法运算
+  RationalExtend operator -(RationalExtend other) {
+    List<Ksqrt> newTerms = List.from(terms);
+    for (var term in other.terms) {
+      newTerms.add(Ksqrt(-term.k, term.q));
+    }
+
+    RationalExtend result = RationalExtend(newTerms);
+    result.simplify();
+    return result;
+  }
+
+  // 乘法运算
+  RationalExtend operator *(RationalExtend other) {
+    List<Ksqrt> productTerms = [];
+
+    for (var term1 in terms) {
+      for (var term2 in other.terms) {
+        productTerms.add(term1 * term2);
+      }
+    }
+
+    RationalExtend result = RationalExtend(productTerms);
+    result.simplify();
+    return result;
+  }
+
+  // 修复的除法运算
+  RationalExtend operator /(RationalExtend other) {
+    if (other.terms.isEmpty) {
+      throw ArgumentError("除数不能为空");
+    }
+
+    // 特殊情况:除数是单项式
+    if (other.terms.length == 1) {
+      List<Ksqrt> newTerms = [];
+      for (var term in terms) {
+        newTerms.add(term / other.terms[0]);
+      }
+      return RationalExtend(newTerms)..simplify();
+    }
+
+    // 一般情况:使用分母有理化
+    RationalExtend conjugate = other.conjugate;
+    RationalExtend numerator = this * conjugate;
+    RationalExtend denominator = other * conjugate;
+
+    if (!denominator.isRational) {
+      throw StateError("分母有理化失败,结果仍包含根号");
+    }
+
+    Rational denomValue = denominator.rationalValue;
+
+    if (denomValue == Rational.zero) {
+      throw ArgumentError("分母有理化后为0,无法进行除法");
+    }
+
+    // 将分子中的每一项除以分母的有理数值
+    List<Ksqrt> resultTerms = [];
+    for (var term in numerator.terms) {
+      resultTerms.add(Ksqrt(term.k / denomValue, term.q));
+    }
+
+    return RationalExtend(resultTerms)..simplify();
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (other is! RationalExtend) return false;
+
+    RationalExtend thisSimplified = RationalExtend(List.from(terms))..simplify();
+    RationalExtend otherSimplified = RationalExtend(List.from(other.terms))..simplify();
+
+    if (thisSimplified.terms.length != otherSimplified.terms.length) return false;
+
+    for (int i = 0; i < thisSimplified.terms.length; i++) {
+      if (thisSimplified.terms[i] != otherSimplified.terms[i]) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  @override
+  int get hashCode {
+    RationalExtend simplified = RationalExtend(List.from(terms))..simplify();
+    return simplified.terms.fold(0, (hash, term) => hash ^ term.hashCode);
+  }
+
+  // 计算表达式的近似浮点数值
+  double toDouble() {
+    double sum = 0.0;
+    for (var term in terms) {
+      sum += term.toDouble();
+    }
+    return sum;
+  }
+
+  @override
+  String toString() {
+    if (terms.isEmpty) return "0";
+
+    RationalExtend simplified = RationalExtend(List.from(terms))..simplify();
+
+    if (simplified.terms.isEmpty) return "0";
+
+    List<String> termStrings = [];
+    for (var term in simplified.terms) {
+      String termStr = term.toString();
+      if (termStr.startsWith('-')) {
+        termStrings.add(termStr);
+      } else if (termStrings.isNotEmpty) {
+        termStrings.add('+$termStr');
+      } else {
+        termStrings.add(termStr);
+      }
+    }
+
+    String result = termStrings.join('');
+    if (result.startsWith('+')) {
+      result = result.substring(1);
+    }
+
+    return result;
+  }
+}
+
+extension RationalExtendMath on RationalExtend {
+  RationalExtend square() {
+    return this * this;
+  }
+
+  RationalExtend abs() {
+    double value = this.toDouble();
+    if (value < 0) {
+      return RationalExtend(terms.map((term) => Ksqrt(-term.k, term.q)).toList());
+    }
+    return this;
+  }
+
+  bool get isZero {
+    RationalExtend simplified = RationalExtend(List.from(terms))..simplify();
+    return simplified.terms.length == 1 &&
+    simplified.terms[0].k == Rational.zero;
+  }
+
+  Rational get rationalPart {
+    Rational sum = Rational.zero;
+    for (var term in terms) {
+      if (term.q == 1) {
+        sum += term.k;
+      }
+    }
+    return sum;
+  }
+
+  RationalExtend get irrationalPart {
+    List<Ksqrt> irrationalTerms = [];
+    for (var term in terms) {
+      if (term.q != 1) {
+        irrationalTerms.add(term);
+      }
+    }
+    return RationalExtend(irrationalTerms)..simplify();
+  }
+}
+/*测试用例
+// 测试函数 - 增加小数测试
+void main() {
+  print('=== Ksqrt 类测试 ===');
+
+  // 基本创建和化简
+  var sqrt8 = Ksqrt(Rational.one, 8);
+  sqrt8.simplify();
+  print('√8 = $sqrt8'); // 应该输出 2√2
+
+  // 算术运算
+  var a = Ksqrt.parse('√2');
+  var b = Ksqrt.parse('3√2');
+  var sum = a + b;
+  print('√2 + 3√2 = $sum'); // 应该输出 4√2
+
+  var product = a * b;
+  print('√2 * 3√2 = $product'); // 应该输出 6
+
+  // 除法测试 - 修复后
+  var c = Ksqrt.parse('√6');
+  var d = Ksqrt.parse('√3');
+  var quotient = c / d;
+  print('√6 / √3 = $quotient'); // 应该输出 √2
+
+  print('\n=== RationalExtend 类测试 ===');
+
+  // 多项式创建和运算
+  var expr1 = RationalExtend.parse('√2 + 2√3');
+  var expr2 = RationalExtend.parse('√2 - √3');
+  print('表达式1: $expr1');
+  print('表达式2: $expr2');
+
+  var polySum = expr1 + expr2;
+  print('相加: $polySum'); // 应该输出 2√2 + √3
+
+  var polyProduct = expr1 * expr2;
+  print('相乘: $polyProduct'); // 应该输出 2 + √6 - 2√3 - 2*3 = -4 + √6 - 2√3
+
+  // 除法测试(分母有理化)- 修复后
+  try {
+    var polyQuotient = expr1 / expr2;
+    print('相除: $polyQuotient'); // 应该输出有理化后的结果
+  } catch (e) {
+    print('除法错误: $e');
+  }
+
+  // 复杂表达式测试
+  print('\n=== 复杂表达式测试 ===');
+  try {
+    var complexExpr = RationalExtend.parse('2/3');
+    print('分数解析: $complexExpr');
+
+    var complexExpr2 = RationalExtend.parse('2/3+√2');
+    print('分数+根号解析: $complexExpr2');
+
+    var complexExpr3 = RationalExtend.parse('1+√2');
+    var mul = complexExpr2 * complexExpr3;
+    print('复杂表达式1: $complexExpr2');
+    print('复杂表达式2: $complexExpr3');
+    print('乘积: $mul');
+    print('有理数部分: ${complexExpr2.rationalPart}');
+    print('无理数部分: ${complexExpr2.irrationalPart}');
+    print('近似值: ${complexExpr2.toDouble()}');
+  } catch (e) {
+    print('解析错误: $e');
+  }
+
+  // 更多测试
+  print('\n=== 更多测试 ===');
+  try {
+    var test1 = Ksqrt.parse('1/2');
+    print('分数 1/2: $test1');
+
+    var test2 = Ksqrt.parse('3/4*√2');
+    print('分数系数 3/4*√2: $test2');
+
+    var test3 = RationalExtend.parse('1/2 + 1/3*√2');
+    print('混合表达式: $test3');
+  } catch (e) {
+    print('测试错误: $e');
+  }
+
+  // 小数测试
+  print('\n=== 小数支持测试 ===');
+  try {
+    var decimal1 = Ksqrt.parse('0.5');
+    print('小数 0.5: $decimal1');
+
+    var decimal2 = Ksqrt.parse('0.25√2');
+    print('小数系数 0.25√2: $decimal2');
+
+    var decimal3 = Ksqrt.parse('1.5√3');
+    print('小数系数 1.5√3: $decimal3');
+
+    var decimal4 = RationalExtend.parse('0.5 + 3/2√2');
+    print('混合小数表达式: $decimal4');
+
+    var decimal5 = RationalExtend.parse('1/3 + 0.666√2');
+    print('混合小数表达式: $decimal5');
+
+    // 小数运算测试
+    var decimalExpr1 = RationalExtend.parse('0.5√2');
+    var decimalExpr2 = RationalExtend.parse('0.25√2');
+    var decimalSum = decimalExpr1 + decimalExpr2;
+    print('0.5√2 + 0.25√2 = $decimalSum'); // 应该输出 0.75√2
+
+    var decimalProduct = decimalExpr1 * decimalExpr2;
+    print('0.5√2 * 0.25√2 = $decimalProduct'); // 应该输出 0.25
+
+  } catch (e) {
+    print('小数测试错误: $e');
+  }
+}
+*/

+ 25 - 0
removeEmptyFolders.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+# 移除目标文件夹下的空文件夹
+# 检查参数个数
+if [ $# -ne 1 ]; then
+   echo "Usage: $0 <target_directory>"
+   exit 1
+fi
+
+# 获取目标文件夹路径
+target_directory="$1"
+
+# 设置退出状态码为0
+exit_code=0
+
+# 查找并删除空文件夹
+find "$target_directory" -type d -empty -exec rmdir {} \;
+
+# 如果find命令没有找到任何空文件夹,则退出代码为1
+if [ $? -ne 0 ]; then
+   exit_code=1
+fi
+
+# 输出退出状态码
+echo "Exit code: $exit_code"
+exit $exit_code

+ 29 - 0
word2pptx.py

@@ -0,0 +1,29 @@
+import os
+from docx import Document
+from PIL import ImageGrab
+
+def save_images(doc, folder_path):
+   if not os.path.exists(folder_path):
+       os.makedirs(folder_path)
+
+   for index, paragraph in enumerate(doc.paragraphs):
+       if paragraph.style.name.startswith('Heading'):
+           question = paragraph.text
+           answer = doc.paragraphs[index + 1].text
+           save_image(question, answer, folder_path)
+
+
+
+def save_image(question, answer, folder_path):
+   image_name = f"{question.replace(' ', '-')}.png"
+   image_path = os.path.join(folder_path, image_name)
+   print(f"Saving image {image_name}...")
+   image = ImageGrab.grab(question)
+   image.save(image_path)
+
+if __name__ == "__main__":
+   word_file = "test.docx"
+   folder_path = "images"
+
+   doc = Document(word_file)
+   save_images(doc, folder_path)

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 201 - 0
大纲设计工具.html


+ 68 - 0
小分表/excel.sh/average.sh

@@ -0,0 +1,68 @@
+#!/bin/bash
+
+if [ $# -lt 3 ]; then
+    echo "Usage: $0 <csv_file> <class_column> <sum_column1> [<sum_column2> ...]"
+    exit 1
+fi
+
+csv_file="$1"
+class_col="$2"
+shift 2
+sum_cols=("$@")
+
+if [ ! -f "$csv_file" ]; then
+    echo "Error: File '$csv_file' not found!"
+    exit 1
+fi
+
+awk -v class_col="$class_col" -v sum_cols="${sum_cols[*]}" '
+BEGIN {
+    FS = ",";
+    OFS = ",";
+    split(sum_cols, sum_cols_arr, " ")
+    num_sum = length(sum_cols_arr)
+
+    # 初始化多维数组(使用SUBSEP组合键)
+    delete keys
+}
+
+{
+    # 获取分类键
+    key = $class_col
+
+    # 记录唯一分类键
+    if (!(key in key_map)) {
+        keys[++key_count] = key
+        key_map[key] = 1
+    }
+
+    # 累加各汇总列
+    for (i=1; i<=num_sum; i++) {
+        col = sum_cols_arr[i]
+        value = $col+0  # 强制转换为数值
+        sum[key,i] += value
+        count[key,i]++
+    }
+}
+
+END {
+    # 输出标题行
+    #printf "%s", $class_col
+    #for (i=1; i<=num_sum; i++) {
+    #    printf "%savg(%s)", OFS, sum_cols_arr[i]
+    #}
+    #print ""
+
+    # 输出汇总结果
+    for (k=1; k<=key_count; k++) {
+        key = keys[k]
+        printf "%s", key
+        for (i=1; i<=num_sum; i++) {
+            cnt = count[key,i]
+            avg = cnt ? sum[key,i]/cnt : 0
+            printf "%s%.2f", OFS, avg
+        }
+        print ""
+    }
+}
+' "$csv_file"

+ 475 - 0
小分表/excel.sh/excel.sh.md

@@ -0,0 +1,475 @@
+# 小分表
+
+usage: ./main.sh 输入.csv (选择题则加上任意参数)
+
+输入的csv文件要求:有标题行
+
+输入示例:
+
+```csv
+姓名,考号,学号,班级,总分,客观题,主观题,学校排名,班级排名,客 | 一.1,客 | 一.2,客 | 一.3,客 | 一.4,客 | 一.5,客 | 一.6,客 | 一.7,客 | 一.8,客 | 二.9,客 | 二.10,客 | 二.11,主 | 三,主 | 四,主 | 五,主 | 六,主 | 七,主 | 八
+李甲,1.65202E+13,1.65202E+13,41,135.00 ,56.00 ,79.00 ,1.00 ,1.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,6.00 ,4.00 ,6.00 ,15.00 ,12.00 ,15.00 ,6.00 ,17.00 ,14.00 
+张乙,1.65202E+13,1.65202E+13,41,134.00 ,56.00 ,78.00 ,2.00 ,2.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,6.00 ,4.00 ,6.00 ,15.00 ,13.00 ,15.00 ,9.00 ,17.00 ,9.00 
+王丙,1.65202E+13,1.65202E+13,41,133.00 ,58.00 ,75.00 ,3.00 ,3.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,6.00 ,6.00 ,6.00 ,10.00 ,13.00 ,15.00 ,8.00 ,17.00 ,12.00 
+殷麻子,1.65202E+13,1.65202E+13,41,132.00 ,56.00 ,76.00 ,4.00 ,4.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,5.00 ,6.00 ,4.00 ,6.00 ,15.00 ,13.00 ,15.00 ,8.00 ,16.00 ,9.00
+```
+
+
+
+#  筛选
+
+ 以下是实现CSV筛选功能的Shell脚本:
+
+```bash
+#!/bin/bash
+
+# 参数检查
+if [ $# -ne 3 ]; then
+    echo "用法: $0 文件 列名或列号 比较值"
+    exit 1
+fi
+
+file="$1"
+column="$2"
+value="$3"
+
+# 文件存在性检查
+if [ ! -f "$file" ]; then
+    echo "错误: 文件 '$file' 不存在"
+    exit 1
+fi
+
+# 列号解析逻辑
+if [[ "$column" =~ ^[0-9]+$ ]]; then
+    col_num=$column
+else
+    col_num=$(awk -F, -v col="$column" 'NR==1 {
+        for(i=1; i<=NF; i++) {
+            if(tolower($i) == tolower(col)) {
+                print i
+                exit
+            }
+        }
+    }' "$file")
+    
+    if [ -z "$col_num" ]; then
+        echo "错误: 列名 '$column' 未找到"
+        exit 1
+    fi
+fi
+
+# 执行筛选的AWK命令
+awk -F, -v col="$col_num" -v val="$value" '
+BEGIN { OFS=FS }
+NR == 1 { 
+    print
+    next 
+}
+col < 1 || col > NF {
+    print "错误: 无效列号 "col | "cat >&2"
+    exit 1
+}
+$col+0 > val+0
+' "$file"
+```
+
+### 使用方法:
+```bash
+./script.sh 文件名 列名/列号 比较值
+```
+
+### 功能特点:
+1. 自动识别列名(不区分大小写)或列号
+2. 保留CSV表头
+3. 智能数值转换(自动过滤非数值内容)
+4. 完善的错误检查机制
+
+### 示例:
+测试文件 data.csv:
+```csv
+ID,Product,Price,Stock
+101,Apple,3.5,200
+102,Banana,2.8,150
+103,Orange,4.2,80
+104,Mango,5.5,50
+```
+
+1. 筛选价格大于4的产品:
+```bash
+./script.sh data.csv Price 4
+```
+
+输出结果:
+```csv
+ID,Product,Price,Stock
+103,Orange,4.2,80
+104,Mango,5.5,50
+```
+
+2. 使用列号筛选库存小于100的产品:
+```bash
+./script.sh data.csv 4 100
+```
+
+输出结果:
+```csv
+ID,Product,Price,Stock
+103,Orange,4.2,80
+104,Mango,5.5,50
+```
+
+### 注意事项:
+- 确保CSV文件第一行为表头
+- 比较时会自动过滤非数值内容(如文字会被视为0)
+- 列号从1开始计数
+- 支持浮点数比较
+- 特殊字符需进行适当转义
+
+
+
+#  分类汇总
+
+以下是一个支持多列平均值汇总的Shell脚本,可以按指定分组列对多个数值列进行平均值计算:
+
+```bash
+#!/bin/bash
+
+# 参数解析
+usage() {
+    echo "用法: $0 -f 输入文件 -k 分组列 -s 汇总列(多个用逗号分隔)"
+    echo "示例: $0 -f data.csv -k Region -s Sales,Profit"
+    exit 1
+}
+
+# 初始化变量
+input_file=""
+group_col=""
+sum_cols=""
+
+# 解析命令行参数
+while getopts "f:k:s:" opt; do
+    case $opt in
+        f) input_file="$OPTARG" ;;
+        k) group_col="$OPTARG" ;;
+        s) sum_cols="$OPTARG" ;;
+        *) usage ;;
+    esac
+done
+
+# 检查必要参数
+[[ -z "$input_file" || -z "$group_col" || -z "$sum_cols" ]] && usage
+
+# 检查文件是否存在
+[ ! -f "$input_file" ] && { echo "错误: 文件不存在"; exit 1; }
+
+# 读取标题行
+headers=$(head -n 1 "$input_file")
+IFS=',' read -ra headers_arr <<< "$headers"
+num_cols=${#headers_arr[@]}
+
+# 列号转换函数
+get_col_index() {
+    local param="$1"
+    if [[ "$param" =~ ^[0-9]+$ ]]; then
+        [ "$param" -gt 0 ] && [ "$param" -le "$num_cols" ] || { echo "错误: 列号越界"; exit 1; }
+        echo "$param"
+    else
+        for i in "${!headers_arr[@]}"; do
+            [ "${headers_arr[i]}" == "$param" ] && { echo "$((i+1))"; return; }
+        done
+        echo "错误: 列名 '$param' 不存在" >&2
+        exit 1
+    fi
+}
+
+# 获取分组列索引
+group_index=$(get_col_index "$group_col")
+
+# 处理多个汇总列
+IFS=',' read -ra sum_columns <<< "$sum_cols"
+declare -a sum_indices
+
+for col in "${sum_columns[@]}"; do
+    idx=$(get_col_index "$col")
+    # 检查是否为数值列
+    sample_val=$(awk -F, -v col="$idx" 'NR==2 {print $col; exit}' "$input_file")
+    [[ "$sample_val" =~ ^-?[0-9]+(\.[0-9]+)?$ ]] || { echo "错误: 列 '$col' 包含非数值数据"; exit 1; }
+    sum_indices+=("$idx")
+done
+
+# 构建AWK命令
+awk_script='
+BEGIN {
+    OFS = ","
+    FS = ","
+    # 打印标题行
+    printf "%s", group_header
+    for (i=0; i<num_sum_cols; i++) {
+        printf ",Avg_%s", sum_headers[i]
+    }
+    printf "\n"
+}
+NR == 1 { next }  # 跳过标题行
+{
+    key = $group_col
+    # 初始化计数器
+    if (!(key in count)) {
+        count[key] = 0
+        for (i=0; i<num_sum_cols; i++) {
+            sum[key,i] = 0
+        }
+    }
+    count[key]++
+    
+    # 累加各列值
+    for (i=0; i<num_sum_cols; i++) {
+        sum[key,i] += $sum_indices[i]
+    }
+}
+END {
+    # 输出结果
+    for (k in count) {
+        printf "%s", k
+        for (i=0; i<num_sum_cols; i++) {
+            avg = sum[k,i] / count[k]
+            printf ",%.2f", avg  # 保留两位小数
+        }
+        printf "\n"
+    }
+}
+'
+
+# 执行AWK处理
+awk -v group_header="${headers_arr[group_index-1]}" \
+    -v num_sum_cols="${#sum_indices[@]}" \
+    -v group_col="$group_index" \
+    -v sum_indices="${sum_indices[*]}" \
+    -v sum_headers="${sum_columns[*]}" \
+    '
+BEGIN {
+    split(sum_indices, sum_indices_arr, " ")
+    split(sum_headers, sum_headers_arr, " ")
+}
+'"$awk_script" "$input_file" | sort -t, -k1
+```
+
+**使用说明:**
+
+1. 保存为`multi_avg_groupby.sh`
+2. 赋予执行权限:`chmod +x multi_avg_groupby.sh`
+3. 使用格式:`./multi_avg_groupby.sh -f 文件 -k 分组列 -s 汇总列1,汇总列2,...`
+
+**参数说明:**
+- `-f`: CSV文件路径
+- `-k`: 分组列名或编号(1-based)
+- `-s`: 多个汇总列名或编号,用逗号分隔
+
+**示例:**
+```bash
+# 按Region分组,同时计算Sales和Profit的平均值
+./multi_avg_groupby.sh -f data.csv -k Region -s Sales,Profit
+
+# 按第2列分组,计算第3和第5列的平均值
+./multi_avg_groupby.sh -f data.csv -k 2 -s 3,5
+```
+
+**功能特点:**
+1. 支持多列同时计算平均值
+2. 自动识别列名或列号
+3. 结果保留两位小数
+4. 动态生成包含所有汇总列的标题行
+5. 数值类型安全检查
+6. 结果按分组列排序
+
+**输出示例:**
+```
+Region,Avg_Sales,Avg_Profit
+East,1523.50,423.80
+West,1821.25,598.30
+```
+
+**注意事项:**
+1. CSV文件必须包含标题行
+2. 所有汇总列必须为数值类型
+3. 使用简单排序,如需复杂排序可修改最后的sort命令
+4. 处理超大文件时性能有限,建议使用专业工具处理超大数据集
+
+这个脚本可以同时处理多个数值列的平均值计算,输出结果会为每个汇总列单独生成平均值列,适合需要同时分析多个指标的场景。
+
+# 排序
+
+ 
+
+```shell
+#!/bin/bash
+
+# 输入检查
+if [ $# -lt 2 ]; then
+    echo "用法: $0 <CSV文件> <排序列名> [numeric]"
+    echo "示例: $0 data.csv Age numeric"
+    exit 1
+fi
+
+input_file="$1"
+sort_column="$2"
+numeric_sort="${3:-text}"
+
+# 检查文件是否存在
+if [ ! -f "$input_file" ]; then
+    echo "错误: 文件 '$input_file' 未找到"
+    exit 1
+fi
+
+# 提取标题行
+header=$(head -n 1 "$input_file")
+
+# 确定列索引
+column_index=$(echo "$header" | awk -F, -v col="$sort_column" '{
+    for(i=1; i<=NF; i++) {
+        if ($i == col) {
+            print i
+            exit
+        }
+    }
+    print -1
+}')
+
+# 列名检查
+if [ "$column_index" -eq -1 ]; then
+    echo "错误: 列 '$sort_column' 在标题中未找到"
+    exit 1
+fi
+
+# 设置排序参数
+sort_options="-t, -k$column_index,$column_index"
+[ "$numeric_sort" = "numeric" ] && sort_options="$sort_options -n"
+
+# 执行排序并输出
+echo "$header"
+tail -n +2 "$input_file" | sort $sort_options
+
+```
+
+使用说明:
+
+保存为 sort_csv.sh
+赋予执行权限:chmod +x sort_csv.sh
+基本用法:./sort_csv.sh 文件名.csv 列名
+数值排序:./sort_csv.sh 文件名.csv 列名 numeric
+
+# 格式化输出
+
+ 
+
+以下是一个能够将CSV文件转换为易读格式的Shell脚本,使用`awk`动态计算列宽并格式化输出:
+
+```bash
+#!/bin/bash
+
+# 检查输入参数
+if [ $# -ne 1 ]; then
+    echo "用法: $0 <csv文件>"
+    exit 1
+fi
+
+csv_file="$1"
+txt_file="${csv_file%.*}.formatted.txt"
+
+# 使用awk处理CSV
+awk -F ',' '
+BEGIN {
+    # 定义表格元素
+    OFS = " | "
+    hline_char = "-"
+}
+
+NR == 1 {
+    # 读取表头
+    for (i=1; i<=NF; i++) {
+        gsub(/"/, "", $i)  # 去除字段中的双引号
+        header[i] = $i
+        max_width[i] = length($i)
+    }
+}
+
+NR > 1 {
+    # 更新最大列宽
+    for (i=1; i<=NF; i++) {
+        gsub(/"/, "", $i)  # 去除字段中的双引号
+        w = length($i)
+        if (w > max_width[i]) max_width[i] = w
+    }
+}
+
+END {
+    # 打印表头
+    printf("|")
+    for (i=1; i<=NF; i++) {
+        printf(" %-"max_width[i]"s |", header[i])
+    }
+    printf "\n"
+
+    # 打印分隔线
+    printf("|")
+    for (i=1; i<=NF; i++) {
+        printf("%s", hline_char)
+        for (j=0; j<max_width[i]+2; j++) printf("%s", hline_char)
+        printf("|")
+    }
+    printf "\n"
+
+    # 打印数据行
+    while (getline line < "'"$csv_file"'") {
+        if (++counter == 1) continue  # 跳过表头
+        $0 = line
+        printf("|")
+        for (i=1; i<=NF; i++) {
+            gsub(/"/, "", $i)
+            printf(" %-"max_width[i]"s |", $i)
+        }
+        printf "\n"
+    }
+}' "$csv_file" > "$txt_file"
+
+echo "格式化完成: $txt_file"
+```
+
+### 功能说明:
+1. **动态列宽计算**:自动检测每列最大宽度
+2. **表格格式化**:
+   - 使用管道符 `|` 分隔列
+   - 自动添加表头与数据分隔线
+   - 支持文本左对齐
+3. **特殊处理**:
+   - 去除字段中的双引号
+   - 自动跳过空行
+   - 支持包含空格和特殊字符的字段
+
+### 使用方式:
+```bash
+chmod +x csv_formatter.sh
+./csv_formatter.sh input.csv
+```
+
+### 示例输入 (input.csv):
+```csv
+ID,Name,Department,Start Date
+1,Alice Smith,"Engineering, R&D",2020-03-15
+2,Bob Johnson,Marketing,2019-07-01
+```
+
+### 输出 (input.formatted.txt):
+```
+| ID | Name         | Department       | Start Date  |
+|----|--------------|------------------|-------------|
+| 1  | Alice Smith  | Engineering, R&D | 2020-03-15  |
+| 2  | Bob Johnson  | Marketing        | 2019-07-01  |
+```
+
+### 注意事项:
+1. 假设CSV文件使用标准逗号分隔
+2. 支持带双引号的字段(自动去除引号)
+3. 最大支持100列(可根据需要调整awk的`max_width`数组大小)
+4. 输入文件需小于2GB(受awk限制)
+
+对于包含复杂格式(如换行符、嵌套逗号)的CSV文件,建议先使用`csvkit`等专业工具进行预处理。

+ 50 - 0
小分表/excel.sh/filter.sh

@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# 参数检查
+if [ $# -ne 3 ]; then
+    echo "用法: $0 文件 列名或列号 比较值"
+    exit 1
+fi
+
+file="$1"
+column="$2"
+value="$3"
+
+# 文件存在性检查
+if [ ! -f "$file" ]; then
+    echo "错误: 文件 '$file' 不存在"
+    exit 1
+fi
+
+# 列号解析逻辑
+if [[ "$column" =~ ^[0-9]+$ ]]; then
+    col_num=$column
+else
+    col_num=$(awk -F, -v col="$column" 'NR==1 {
+        for(i=1; i<=NF; i++) {
+            if(tolower($i) == tolower(col)) {
+                print i
+                exit
+            }
+        }
+    }' "$file")
+
+    if [ -z "$col_num" ]; then
+        echo "错误: 列名 '$column' 未找到"
+        exit 1
+    fi
+fi
+
+# 执行筛选的AWK命令
+awk -F, -v col="$col_num" -v val="$value" '
+BEGIN { OFS=FS }
+NR == 1 {
+    print
+    next
+}
+col < 1 || col > NF {
+    print "错误: 无效列号 "col | "cat >&2"
+    exit 1
+}
+$col+0 > val+0
+' "$file"

+ 27 - 0
小分表/excel.sh/main.sh

@@ -0,0 +1,27 @@
+#!/bin/bash
+file="$1" #获取文件名
+
+# 文件存在性检查
+if [ ! -f "$file" ]; then
+    echo "错误: 文件 '$file' 不存在"
+    exit 1
+fi
+
+sh filter.sh $1 总分 5 > 1.csv
+sh average.sh 1.csv 4 5 6 7 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 > 2.csv
+if [ -z "$2" ]; then
+    echo "班级,总分,客观题,主观题,1,2,3,4,5,6,7,8,9,10,11,填空,15,16,17,18,19" > 2.5.csv #如果没有第二个参数就是总分模式
+else
+    echo "班级,客观题,1,2,3,4,5,6,7,8,9,10,11" > 2.5.csv #如果有第二个参数就是选择题模式
+fi
+
+
+tail -n +2 2.csv >> 2.5.csv
+sh sort.sh 2.5.csv 班级 numeric > 3.csv
+sh output.sh 3.csv
+rm -f 1.csv
+rm -f 2.csv
+rm -f 2.5.csv
+mv 3.csv output.csv
+mv 3.formatted.txt output.txt
+cat output.txt

+ 66 - 0
小分表/excel.sh/output.sh

@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# 检查输入参数
+if [ $# -ne 1 ]; then
+    echo "用法: $0 <csv文件>"
+    exit 1
+fi
+
+csv_file="$1"
+txt_file="${csv_file%.*}.formatted.txt"
+
+# 使用awk处理CSV
+awk -F ',' '
+BEGIN {
+    # 定义表格元素
+    OFS = " | "
+    hline_char = "-"
+}
+
+NR == 1 {
+    # 读取表头
+    for (i=1; i<=NF; i++) {
+        gsub(/"/, "", $i)  # 去除字段中的双引号
+        header[i] = $i
+        max_width[i] = length($i)
+    }
+}
+
+NR > 1 {
+    # 更新最大列宽
+    for (i=1; i<=NF; i++) {
+        gsub(/"/, "", $i)  # 去除字段中的双引号
+        w = length($i)
+        if (w > max_width[i]) max_width[i] = w
+    }
+}
+
+END {
+    # 打印表头
+    printf("|")
+    for (i=1; i<=NF; i++) {
+        printf(" %-"max_width[i]"s |", header[i])
+    }
+    printf "\n"
+
+    # 打印分隔线
+    printf("|")
+    for (i=1; i<=NF; i++) {
+        printf("%s", hline_char)
+        for (j=0; j<max_width[i]+2; j++) printf("%s", hline_char)
+        printf("|")
+    }
+    printf "\n"
+
+    # 打印数据行
+    while (getline line < "'"$csv_file"'") {
+        if (++counter == 1) continue  # 跳过表头
+        $0 = line
+        printf("|")
+        for (i=1; i<=NF; i++) {
+            gsub(/"/, "", $i)
+            printf(" %-"max_width[i]"s |", $i)
+        }
+        printf "\n"
+    }
+}' "$csv_file" > "$txt_file"

+ 46 - 0
小分表/excel.sh/sort.sh

@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# 输入检查
+if [ $# -lt 2 ]; then
+    echo "用法: $0 <CSV文件> <排序列名> [numeric]"
+    echo "示例: $0 data.csv Age numeric"
+    exit 1
+fi
+
+input_file="$1"
+sort_column="$2"
+numeric_sort="${3:-text}"
+
+# 检查文件是否存在
+if [ ! -f "$input_file" ]; then
+    echo "错误: 文件 '$input_file' 未找到"
+    exit 1
+fi
+
+# 提取标题行
+header=$(head -n 1 "$input_file")
+
+# 确定列索引
+column_index=$(echo "$header" | awk -F, -v col="$sort_column" '{
+    for(i=1; i<=NF; i++) {
+        if ($i == col) {
+            print i
+            exit
+        }
+    }
+    print -1
+}')
+
+# 列名检查
+if [ "$column_index" -eq -1 ]; then
+    echo "错误: 列 '$sort_column' 在标题中未找到"
+    exit 1
+fi
+
+# 设置排序参数
+sort_options="-t, -k$column_index,$column_index"
+[ "$numeric_sort" = "numeric" ] && sort_options="$sort_options -n"
+
+# 执行排序并输出
+echo "$header"
+tail -n +2 "$input_file" | sort $sort_options

+ 524 - 0
小分表/python版/main.py

@@ -0,0 +1,524 @@
+#拉小分表工具(即分类汇总)
+import sys
+import pandas as pd
+from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton,
+                            QFileDialog, QTableWidget, QTableWidgetItem, QSpinBox,
+                            QLabel, QProgressBar, QCheckBox, QLineEdit, QHBoxLayout, QComboBox)
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QColor
+import matplotlib.pyplot as plt
+import ast
+plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
+plt.rcParams['axes.unicode_minus'] = False
+
+class ExcelProcessor(QWidget):
+    def __init__(self):
+        super().__init__()
+        # 先定义属性,再初始化UI
+        self.df = pd.DataFrame()
+        self.threshold = 10
+        self.ignore_cols = [1,2,3,8,9]  # 默认忽略列索引
+        self.current_file_path = None  # 添加当前文件路径属性
+        self.color_groups = []  # 存储班级颜色分组
+        self.current_result_df = None  # 存储当前处理结果
+        self.current_group_col = None  # 存储当前分组列名
+        self.initUI()
+
+    def initUI(self):
+        self.setWindowTitle('Excel数据处理工具')
+        self.setGeometry(300, 300, 800, 600)
+
+        layout = QVBoxLayout()
+
+        # 文件选择
+        self.btn_open = QPushButton('选择Excel文件', self)
+        self.btn_open.clicked.connect(self.open_file)
+        layout.addWidget(self.btn_open)
+
+        # 文件路径显示
+        self.lbl_file_path = QLabel('未选择文件', self)
+        layout.addWidget(self.lbl_file_path)
+
+        # 忽略列设置
+        self.ignore_layout = QHBoxLayout()
+        self.lbl_ignore = QLabel('忽略列索引:', self)
+        self.txt_ignore = QLineEdit('1,2,3,8,9', self)
+        self.ignore_layout.addWidget(self.lbl_ignore)
+        self.ignore_layout.addWidget(self.txt_ignore)
+        layout.addLayout(self.ignore_layout)
+
+        # 分组列选择
+        self.group_layout = QHBoxLayout()
+        self.lbl_group = QLabel('分组列:', self)
+        self.cmb_group = QComboBox(self)
+        self.group_layout.addWidget(self.lbl_group)
+        self.group_layout.addWidget(self.cmb_group)
+        layout.addLayout(self.group_layout)
+
+        # 阈值设置
+        self.threshold_layout = QVBoxLayout()
+        self.lbl_threshold = QLabel('总分阈值:', self)
+        self.spin_threshold = QSpinBox(self)
+        self.spin_threshold.setValue(self.threshold)  # 现在self.threshold已经定义了
+        self.threshold_layout.addWidget(self.lbl_threshold)
+        self.threshold_layout.addWidget(self.spin_threshold)
+        layout.addLayout(self.threshold_layout)
+        
+        # 班级颜色分组设置
+        self.color_layout = QVBoxLayout()
+        self.lbl_color = QLabel('班级颜色分组 (格式: [1,2,30,31],[3,4,5,6,32,33,34,35],...):', self)
+        self.txt_color = QLineEdit('[1,2,30,31],[3,4,5,6,32,33,34,35],[7,8,9,10,36,37,38,39],[12,13,14,42,43,44],[23,24,41]', self)
+        self.color_layout.addWidget(self.lbl_color)
+        self.color_layout.addWidget(self.txt_color)
+        layout.addLayout(self.color_layout)
+
+        # 处理选项
+        self.chk_header = QCheckBox('包含表头', self)
+        self.chk_header.setChecked(True)
+        self.chk_header.stateChanged.connect(self.on_header_changed)  # 添加状态改变信号连接
+        layout.addWidget(self.chk_header)
+
+        # 处理按钮
+        self.btn_process = QPushButton('开始处理', self)
+        self.btn_process.clicked.connect(self.process_data)
+        self.btn_process.setEnabled(False)  # 初始时禁用处理按钮
+        layout.addWidget(self.btn_process)
+
+        # 进度条
+        self.progress = QProgressBar(self)
+        self.progress.setValue(0)  # 初始化为0
+        layout.addWidget(self.progress)
+
+        # 结果显示
+        self.table_result = QTableWidget(self)
+        layout.addWidget(self.table_result)
+
+        self.setLayout(layout)
+
+    def open_file(self):
+        path, _ = QFileDialog.getOpenFileName(self, '选择Excel文件', '', 'Excel Files (*.xlsx)')
+        if path:
+            self.current_file_path = path  # 保存文件路径
+            self.load_file()
+
+    def load_file(self):
+        """加载文件的方法,供open_file和on_header_changed调用"""
+        if self.current_file_path:
+            try:
+                # 根据复选框状态决定读取方式
+                if self.chk_header.isChecked():
+                    # 包含表头:忽略第一行,将第二行视为标题行,第三行开始为数据
+                    self.df = pd.read_excel(self.current_file_path, header=1)  # header=1 表示第二行作为标题
+                else:
+                    # 不包含表头:第一行视为标题行,第二行开始为数据
+                    self.df = pd.read_excel(self.current_file_path, header=0)  # header=0 表示第一行作为标题
+                    
+                self.lbl_file_path.setText(f'已选择文件: {self.current_file_path.split("/")[-1]}')  # 只显示文件名
+                self.progress.setValue(0)  # 重置进度条
+                
+                # 更新分组列下拉框
+                self.update_group_combo()
+                
+                # 启用处理按钮
+                self.btn_process.setEnabled(True)
+                
+            except Exception as e:
+                print(f"文件读取错误: {str(e)}")
+
+    def on_header_changed(self):
+        """当包含表头复选框状态改变时调用"""
+        if self.current_file_path:  # 如果已经选择了文件
+            self.load_file()  # 重新加载文件
+
+    def update_group_combo(self):
+        """更新分组列下拉框选项"""
+        self.cmb_group.clear()
+        if not self.df.empty:
+            # 添加所有列名
+            for col in self.df.columns:
+                self.cmb_group.addItem(str(col))
+            
+            # 尝试自动选择"班级"列
+            group_keywords = ['班级', '班', 'class', 'Class', 'CLASSS']
+            for keyword in group_keywords:
+                for i in range(self.cmb_group.count()):
+                    if keyword in self.cmb_group.itemText(i):
+                        self.cmb_group.setCurrentIndex(i)
+                        return
+
+    def parse_color_groups(self):
+        """解析班级颜色分组设置"""
+        color_text = self.txt_color.text().strip()
+        if not color_text:
+            return []
+        
+        try:
+            # 使用ast.literal_eval安全地解析字符串
+            # 首先将整个字符串包装在列表中,然后解析
+            parsed = ast.literal_eval(f'[{color_text}]')
+            
+            # 确保结果是列表的列表
+            color_groups = []
+            for item in parsed:
+                if isinstance(item, list):
+                    color_groups.append(item)
+                elif isinstance(item, int):
+                    color_groups.append([item])
+                else:
+                    print(f"忽略无效的分组项: {item}")
+            
+            return color_groups
+        except Exception as e:
+            print(f"解析班级颜色分组时出错: {str(e)}")
+            return []
+
+    def get_class_color(self, class_value):
+        """根据班级值获取对应的颜色索引"""
+        # 尝试将班级值转换为整数进行比较
+        try:
+            class_num = int(class_value)
+        except (ValueError, TypeError):
+            # 如果无法转换为整数,尝试提取数字
+            try:
+                import re
+                numbers = re.findall(r'\d+', str(class_value))
+                if numbers:
+                    class_num = int(numbers[0])
+                else:
+                    class_num = None
+            except:
+                class_num = None
+        
+        # 查找班级所属的颜色组
+        color_index = -1
+        if class_num is not None:
+            for i, group in enumerate(self.color_groups):
+                if class_num in group:
+                    color_index = i
+                    break
+        
+        return color_index
+
+    def process_data(self):
+        if self.df.empty:
+            return
+
+        # 重置进度条
+        self.progress.setValue(0)
+
+        # 解析忽略列
+        try:
+            self.ignore_cols = list(map(int, self.txt_ignore.text().split(',')))
+        except:
+            self.ignore_cols = [1,2,3,8,9]
+
+        # 解析班级颜色分组
+        self.color_groups = self.parse_color_groups()
+
+        # 数据清洗 - 先找到用户选择的分组列的位置
+        selected_group_col = self.cmb_group.currentText()
+        group_col_index = None
+        for i, col in enumerate(self.df.columns):
+            if col == selected_group_col:
+                group_col_index = i
+                break
+        
+        # 确保分组列不被忽略
+        if group_col_index is not None and group_col_index in self.ignore_cols:
+            self.ignore_cols.remove(group_col_index)
+
+        valid_cols = [i for i in range(self.df.shape[1]) if i not in self.ignore_cols]
+        self.df = self.df.iloc[:, valid_cols]
+
+        # 更新分组列下拉框(因为列索引可能已改变)
+        self.update_group_combo()
+        
+        # 重新获取分组列名(因为列索引可能已改变)
+        selected_group_col = self.cmb_group.currentText()
+
+        # 删除低分行
+        score_col = [col for col in self.df.columns if '总分' in str(col)]
+        if score_col:
+            self.df = self.df[pd.to_numeric(self.df[score_col[0]], errors='coerce').notnull()]
+            self.df = self.df[self.df[score_col[0]] >= self.spin_threshold.value()]
+            self.progress.setValue(40)
+
+        # 分类汇总
+        if len(valid_cols) == 0:
+            return
+
+        # 使用用户选择的分组列
+        group_col_name = selected_group_col
+        
+        # 如果用户选择的列不存在,使用备选方案
+        if group_col_name not in self.df.columns:
+            # 查找可能的分组列(班级、班、class等)
+            group_keywords = ['班级', '班', 'class', 'Class', 'CLASSS']
+            group_col_name = None
+            
+            for keyword in group_keywords:
+                for col in self.df.columns:
+                    if keyword in str(col):
+                        group_col_name = col
+                        break
+                if group_col_name:
+                    break
+            
+            # 如果还是找不到,使用第一列作为分组列
+            if group_col_name is None:
+                group_col_name = self.df.columns[0]
+                print(f"警告:未找到班级列,使用第一列 '{group_col_name}' 进行分组")
+
+        numeric_cols = self.df.select_dtypes(include='number').columns.tolist()
+        
+        # 确保分组列不在数值列中
+        if group_col_name in numeric_cols:
+            numeric_cols.remove(group_col_name)
+        
+        if len(numeric_cols) == 0:
+            print("错误:没有找到数值列进行汇总")
+            return
+
+        grouped = self.df.groupby(group_col_name)[numeric_cols].mean().reset_index()
+        
+        # 保留两位小数
+        grouped[numeric_cols] = grouped[numeric_cols].round(2)
+        
+        grouped = grouped.sort_values(by=group_col_name)
+        self.progress.setValue(60)
+
+        # 保存处理结果
+        self.current_result_df = grouped
+        self.current_group_col = group_col_name
+
+        # 显示结果
+        self.display_result(grouped, group_col_name)
+
+    def display_result(self, df, group_col_name):
+        self.table_result.setRowCount(len(df))
+        self.table_result.setColumnCount(len(df.columns))
+        
+        # 设置表头
+        self.table_result.setHorizontalHeaderLabels(df.columns)
+        
+        # 预定义颜色列表
+        colors = [
+            QColor(255, 200, 200),  # 浅红色
+            QColor(200, 255, 200),  # 浅绿色
+            QColor(200, 200, 255),  # 浅蓝色
+            QColor(255, 255, 200),  # 浅黄色
+            QColor(255, 200, 255),  # 浅紫色
+            QColor(200, 255, 255),  # 浅青色
+            QColor(255, 220, 200),  # 浅橙色
+            QColor(220, 200, 255),  # 浅紫罗兰色
+        ]
+        
+        # 填充数据并设置颜色
+        for row in range(len(df)):
+            class_value = df.iloc[row][group_col_name]
+            color_index = self.get_class_color(class_value)
+            
+            for col in range(len(df.columns)):
+                item = QTableWidgetItem(str(df.iloc[row, col]))
+                
+                # 如果班级在颜色分组中,设置背景色
+                if color_index >= 0 and color_index < len(colors):
+                    item.setBackground(colors[color_index % len(colors)])
+                
+                self.table_result.setItem(row, col, item)
+        
+        # 完成进度
+        self.progress.setValue(100)
+        
+        # 导出按钮
+        if hasattr(self, 'btn_export'):
+            self.layout().removeWidget(self.btn_export)
+            self.btn_export.deleteLater()
+            
+        self.btn_export = QPushButton('导出结果', self)
+        self.btn_export.clicked.connect(lambda: self.export_data(df))
+        self.layout().addWidget(self.btn_export)
+
+    def export_data(self, df):
+        path, _ = QFileDialog.getSaveFileName(self, '保存结果', '', 
+                                           'Excel Files (*.xlsx);;图片文件 (*.png)')
+        if path:
+            if path.endswith('.xlsx'):
+                self.export_to_excel(df, path)
+            elif path.endswith('.png'):
+                self.save_as_image(df, path)
+
+    def export_to_excel(self, df, path):
+        """导出到Excel并应用颜色和边框"""
+        try:
+            # 检查是否安装了openpyxl
+            try:
+                import openpyxl
+                from openpyxl.styles import PatternFill, Border, Side
+            except ImportError:
+                print("未安装openpyxl,无法导出带颜色的Excel文件")
+                df.to_excel(path, index=False)
+                print(f"已导出无颜色的Excel文件: {path}")
+                return
+            
+            # 使用openpyxl引擎,以便设置单元格样式
+            with pd.ExcelWriter(path, engine='openpyxl') as writer:
+                df.to_excel(writer, index=False, sheet_name='Sheet1')
+                
+                # 获取工作表
+                workbook = writer.book
+                worksheet = writer.sheets['Sheet1']
+                
+                # 定义颜色映射(RGB值)
+                colors_rgb = [
+                    'FFFFC8C8',  # 浅红色
+                    'FFC8FFC8',  # 浅绿色
+                    'FFC8C8FF',  # 浅蓝色
+                    'FFFFFFC8',  # 浅黄色
+                    'FFFFC8FF',  # 浅紫色
+                    'FFC8FFFF',  # 浅青色
+                    'FFFFDCC8',  # 浅橙色
+                    'FFDCC8FF',  # 浅紫罗兰色
+                ]
+                
+                # 定义边框样式
+                thin_border = Border(
+                    left=Side(style='thin'),
+                    right=Side(style='thin'),
+                    top=Side(style='thin'),
+                    bottom=Side(style='thin')
+                )
+                
+                # 为每一行设置背景色和边框
+                for row_idx in range(1, len(df) + 2):  # 从第1行(表头)开始到数据行结束
+                    # 设置背景色(仅对数据行,不包括表头)
+                    if row_idx >= 2:  # 数据行从第2行开始
+                        class_value = df.iloc[row_idx-2][self.current_group_col]
+                        color_index = self.get_class_color(class_value)
+                        
+                        if color_index >= 0 and color_index < len(colors_rgb):
+                            fill_color = colors_rgb[color_index % len(colors_rgb)]
+                            
+                            # 为这一行的所有单元格设置背景色
+                            for col_idx in range(1, len(df.columns) + 1):
+                                cell = worksheet.cell(row=row_idx, column=col_idx)
+                                cell.fill = PatternFill(start_color=fill_color, 
+                                                       end_color=fill_color, 
+                                                       fill_type='solid')
+                    
+                    # 为所有单元格设置边框(包括表头和数据行)
+                    for col_idx in range(1, len(df.columns) + 1):
+                        cell = worksheet.cell(row=row_idx, column=col_idx)
+                        cell.border = thin_border
+                
+                # 自动调整列宽
+                for column in worksheet.columns:
+                    max_length = 0
+                    column_letter = column[0].column_letter
+                    for cell in column:
+                        try:
+                            if len(str(cell.value)) > max_length:
+                                max_length = len(str(cell.value))
+                        except:
+                            pass
+                    adjusted_width = (max_length + 2)
+                    worksheet.column_dimensions[column_letter].width = adjusted_width
+                
+            print(f"带颜色和边框的Excel文件已保存到: {path}")
+        except Exception as e:
+            print(f"导出带颜色的Excel时出错: {str(e)}")
+            # 如果带颜色的导出失败,尝试普通导出
+            try:
+                df.to_excel(path, index=False)
+                print(f"Excel文件已保存到: {path} (无颜色和边框)")
+            except Exception as e2:
+                print(f"普通Excel导出也失败: {str(e2)}")
+
+    def save_as_image(self, df, path):
+        import matplotlib.pyplot as plt
+        import numpy as np
+
+        fig, ax = plt.subplots(figsize=(12, 8))
+        ax.axis('off')
+        
+        # 获取数据
+        cell_text = []
+        for i in range(len(df)):
+            row_data = []
+            for j in range(len(df.columns)):
+                row_data.append(str(df.iloc[i, j]))
+            cell_text.append(row_data)
+        
+        col_labels = [str(col) for col in df.columns]
+        
+        # 预定义颜色
+        colors_mpl = [
+            [1.0, 0.8, 0.8],    # 浅红色
+            [0.8, 1.0, 0.8],    # 浅绿色
+            [0.8, 0.8, 1.0],    # 浅蓝色
+            [1.0, 1.0, 0.8],    # 浅黄色
+            [1.0, 0.8, 1.0],    # 浅紫色
+            [0.8, 1.0, 1.0],    # 浅青色
+            [1.0, 0.86, 0.8],   # 浅橙色
+            [0.86, 0.8, 1.0],   # 浅紫罗兰色
+        ]
+        
+        # 构建颜色数组 - 关键修复:只包含数据行,不包括表头
+        cell_colors = []
+        
+        # 只添加数据行颜色(不包括表头)
+        for i in range(len(df)):
+            class_value = df.iloc[i][self.current_group_col]
+            color_index = self.get_class_color(class_value)
+            
+            if 0 <= color_index < len(colors_mpl):
+                row_color = colors_mpl[color_index]
+            else:
+                row_color = [1, 1, 1]  # 默认白色
+                
+            row_colors = [row_color for _ in range(len(df.columns))]
+            cell_colors.append(row_colors)
+        
+        # 调试信息
+        print(f"数据行数: {len(df)}")
+        print(f"cell_text 行数: {len(cell_text)}")
+        print(f"cell_colors 行数: {len(cell_colors)}")
+        
+        # 确保行数匹配 - 现在应该都是7行
+        if len(cell_colors) != len(cell_text):
+            print(f"警告: 颜色行数 ({len(cell_colors)}) 与数据行数 ({len(cell_text)}) 不匹配")
+            # 强制调整颜色数组大小
+            if len(cell_colors) > len(cell_text):
+                cell_colors = cell_colors[:len(cell_text)]
+            else:
+                while len(cell_colors) < len(cell_text):
+                    cell_colors.append([[1, 1, 1] for _ in range(len(df.columns))])
+        
+        # 创建表格 - 关键修复:使用colColours参数单独设置表头颜色
+        table = ax.table(
+            cellText=cell_text,
+            colLabels=col_labels,
+            cellLoc='center',
+            loc='center',
+            cellColours=cell_colors,
+            colColours=[[1, 1, 1] for _ in range(len(df.columns))]  # 表头颜色设为白色
+        )
+        
+        table.auto_set_font_size(False)
+        table.set_fontsize(10)
+        table.scale(1, 1.5)
+        
+        # 设置单元格边框
+        for key, cell in table.get_celld().items():
+            cell.set_linewidth(0.5)
+            cell.set_edgecolor('black')
+        
+        plt.savefig(path, bbox_inches='tight', dpi=300)
+        plt.close()
+        print(f"图片已保存到: {path}")
+
+if __name__ == '__main__':
+    app = QApplication(sys.argv)
+    ex = ExcelProcessor()
+    ex.show()
+    sys.exit(app.exec_())

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 7 - 0
小分表/小分表.html


+ 31 - 0
快捷键.py

@@ -0,0 +1,31 @@
+###此脚本用于截图制作ppt,搭配snipaste使用
+#keyboard库用pip安装
+#usage:
+#运行脚本
+#先确保alt+tab可以在ppt和截图文档中切换
+#切换到要截图的页面
+#按下cltr+1开始
+#按F框选,回车截图
+#脚本会自行粘贴并返回
+
+import keyboard
+import time
+
+while True:
+        if keyboard.is_pressed('ctrl') and keyboard.is_pressed('1'):#按下ctrl+1开始监听键盘
+            break
+
+while True:
+    while True:
+        if keyboard.is_pressed('enter'):#监听是否按下回车键
+            break
+    time.sleep(0.5)
+    keyboard.press_and_release("alt+tab")
+    time.sleep(0.5)
+    keyboard.press_and_release("ctrl+m")
+    time.sleep(0.5)
+    keyboard.press_and_release("ctrl+v")
+    time.sleep(0.5)
+    keyboard.press_and_release("alt+tab")
+    
+

BIN
换座位/Temp.xlsx


+ 841 - 0
换座位/座位表.html

@@ -0,0 +1,841 @@
+<!doctype html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <title>座位随机分配(支持性别限制)</title>
+  <link rel="preconnect" href="https://fonts.googleapis.com" />
+  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+  <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@600;700&family=Source+Sans+3:wght@400;600&display=swap" rel="stylesheet" />
+  <script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
+  <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
+  <style>
+    :root {
+      --bg-1: #f2efe8;
+      --bg-2: #dde6f4;
+      --ink: #1f2328;
+      --muted: #5b5f6a;
+      --accent: #1f6feb;
+      --accent-2: #ff7a45;
+      --card: #ffffffd9;
+      --line: #d7dbe2;
+      --seat-on: #1f6feb;
+      --seat-off: #d9dee7;
+      --seat-size: 72px;
+      --male-color: #4dabf7;
+      --female-color: #f783ac;
+    }
+
+    * { box-sizing: border-box; }
+
+    body {
+      margin: 0;
+      font-family: "Source Sans 3", "Segoe UI", sans-serif;
+      color: var(--ink);
+      background: radial-gradient(1200px 700px at 10% 10%, #ffffff 0%, transparent 60%),
+        linear-gradient(135deg, var(--bg-1), var(--bg-2));
+      min-height: 100vh;
+    }
+
+    .wrap {
+      max-width: 1100px;
+      margin: 0 auto;
+      padding: 28px 22px 60px;
+    }
+
+    header {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 16px;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 24px;
+    }
+
+    h1 {
+      margin: 0;
+      font-family: "Noto Serif SC", serif;
+      letter-spacing: 0.04em;
+      font-size: clamp(28px, 3vw, 36px);
+    }
+
+    .pill {
+      background: #fff;
+      border: 1px solid var(--line);
+      border-radius: 999px;
+      padding: 8px 14px;
+      font-size: 13px;
+      color: var(--muted);
+    }
+
+    .grid {
+      display: grid;
+      grid-template-columns: minmax(280px, 1.1fr) minmax(320px, 1.4fr);
+      gap: 18px;
+    }
+
+    .panel {
+      background: var(--card);
+      border: 1px solid var(--line);
+      border-radius: 18px;
+      padding: 18px;
+      box-shadow: 0 18px 40px rgba(18, 30, 57, 0.08);
+      backdrop-filter: blur(4px);
+    }
+
+    .panel h2 {
+      margin: 0 0 12px;
+      font-size: 18px;
+    }
+
+    label {
+      display: block;
+      font-size: 13px;
+      color: var(--muted);
+      margin-bottom: 6px;
+    }
+
+    .row {
+      display: flex;
+      gap: 10px;
+      flex-wrap: wrap;
+      margin-bottom: 12px;
+      align-items: center;
+    }
+
+    input[type="number"],
+    input[type="text"],
+    select {
+      width: 100%;
+      padding: 10px 12px;
+      border-radius: 12px;
+      border: 1px solid var(--line);
+      font-size: 14px;
+    }
+
+    input[type="file"] {
+      width: 100%;
+      border: 1px dashed var(--line);
+      padding: 12px;
+      border-radius: 12px;
+      background: #fff;
+      font-size: 13px;
+    }
+
+    .btn {
+      appearance: none;
+      border: none;
+      background: var(--accent);
+      color: #fff;
+      padding: 10px 14px;
+      border-radius: 12px;
+      font-weight: 600;
+      cursor: pointer;
+      transition: transform 0.15s ease, box-shadow 0.15s ease;
+    }
+
+    .btn.secondary {
+      background: #1f2430;
+    }
+
+    .btn.ghost {
+      background: transparent;
+      border: 1px solid var(--line);
+      color: var(--ink);
+    }
+
+    .btn:disabled {
+      opacity: 0.6;
+      cursor: not-allowed;
+      box-shadow: none;
+    }
+
+    .btn:not(:disabled):hover {
+      transform: translateY(-2px);
+      box-shadow: 0 10px 20px rgba(31, 111, 235, 0.25);
+    }
+
+    .muted {
+      color: var(--muted);
+      font-size: 13px;
+    }
+
+    .seat-grid {
+      display: inline-grid;
+      gap: 8px;
+      margin-top: 14px;
+      padding: 10px;
+      border-radius: 14px;
+      background: #f8f9fc;
+      border: 1px solid var(--line);
+      --seat-size: 72px;
+    }
+
+    .stage-wrap {
+      text-align: center;
+    }
+
+    .seat-stage {
+      display: inline-block;
+      background: #fff;
+      border-radius: 16px;
+      border: 1px solid var(--line);
+      padding: 14px;
+    }
+
+    .stage-label {
+      text-align: center;
+      font-size: 13px;
+      color: var(--muted);
+      margin-bottom: 6px;
+      letter-spacing: 0.04em;
+    }
+
+    .seat {
+      position: relative;
+      border-radius: 10px;
+      border: 1px solid var(--line);
+      min-height: var(--seat-size);
+      background: var(--seat-off);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: clamp(12px, calc(var(--seat-size) / 5.5), 15px);
+      text-align: center;
+      padding: 6px;
+      cursor: pointer;
+      transition: transform 0.12s ease, background 0.2s ease;
+      user-select: none;
+    }
+
+    .seat.active {
+      background: #fff;
+      border-color: #b8c2d6;
+    }
+
+    .seat.assigned {
+      background: var(--seat-on);
+      color: #fff;
+      border-color: #0e4fb3;
+    }
+
+    .seat.assigned.male {
+      background: var(--male-color);
+      border-color: #339af0;
+    }
+
+    .seat.assigned.female {
+      background: var(--female-color);
+      border-color: #f06595;
+    }
+
+    .seat span {
+      display: block;
+      font-weight: 600;
+      font-size: inherit;
+      line-height: 1.3;
+    }
+
+    .seat.assigned span {
+      font-weight: 700;
+      font-size: clamp(14px, calc(var(--seat-size) / 4.2), 20px);
+      letter-spacing: 0.02em;
+    }
+
+    .badge {
+      display: inline-flex;
+      align-items: center;
+      gap: 6px;
+      padding: 6px 10px;
+      border-radius: 999px;
+      background: #fff;
+      border: 1px solid var(--line);
+      font-size: 12px;
+      color: var(--muted);
+    }
+
+    .gender-badge {
+      display: inline-flex;
+      align-items: center;
+      gap: 4px;
+      padding: 4px 8px;
+      border-radius: 6px;
+      font-size: 11px;
+      font-weight: 600;
+    }
+
+    .gender-badge.male {
+      background: rgba(77, 171, 247, 0.1);
+      color: var(--male-color);
+    }
+
+    .gender-badge.female {
+      background: rgba(247, 131, 172, 0.1);
+      color: var(--female-color);
+    }
+
+    .list {
+      max-height: 240px;
+      overflow: auto;
+      border: 1px solid var(--line);
+      border-radius: 12px;
+      padding: 10px;
+      background: #fff;
+      font-size: 13px;
+    }
+
+    .list div {
+      padding: 6px 0;
+      border-bottom: 1px dashed #e7eaf0;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+
+    .list div:last-child {
+      border-bottom: none;
+    }
+
+    .file-hint {
+      font-size: 12px;
+      color: var(--muted);
+      margin-top: 4px;
+      line-height: 1.4;
+    }
+
+    .checkbox-group {
+      display: flex;
+      align-items: center;
+      gap: 8px;
+    }
+
+    .checkbox-group input[type="checkbox"] {
+      width: auto;
+    }
+
+    .checkbox-group label {
+      margin: 0;
+      font-size: 14px;
+    }
+
+    @media (max-width: 900px) {
+      .grid { grid-template-columns: 1fr; }
+    }
+  </style>
+</head>
+<body>
+  <div class="wrap">
+    <header>
+      <div>
+        <h1>座位随机分配(支持性别限制)</h1>
+        <div class="muted">导入带性别的学生名单,设置座位分布,一键随机分配</div>
+      </div>
+      <div class="pill">支持 .xlsx / .xls / .csv(需包含姓名和性别列)</div>
+    </header>
+
+    <section class="grid">
+      <div class="panel">
+        <h2>1. 导入学生名单</h2>
+        <div class="row">
+          <input id="fileInput" type="file" accept=".xlsx,.xls,.csv" />
+        </div>
+        <div class="file-hint">
+          文件格式要求:Excel/CSV文件需包含至少两列,第一列为姓名,第二列为性别(男/女)<br>
+          示例:<br>
+          姓名,性别<br>
+          张三,男<br>
+          李四,女
+        </div>
+        <div class="row">
+          <label>
+            <input id="hasHeader" type="checkbox" checked /> 首行为表头
+          </label>
+        </div>
+        <div class="row">
+          <div style="flex:1">
+            <label>姓名列索引</label>
+            <input id="nameCol" type="number" min="0" value="0" />
+          </div>
+          <div style="flex:1">
+            <label>性别列索引</label>
+            <input id="genderCol" type="number" min="0" value="1" />
+          </div>
+        </div>
+        <div class="row">
+          <button id="loadBtn" class="btn">读取名单</button>
+          <button id="clearBtn" class="btn ghost">清空名单</button>
+        </div>
+        <div class="row">
+          <div class="badge">已导入:<span id="studentCount">0</span> 人</div>
+          <div class="gender-badge male">男生:<span id="maleCount">0</span></div>
+          <div class="gender-badge female">女生:<span id="femaleCount">0</span></div>
+        </div>
+        <div class="list" id="studentList">还没有导入学生</div>
+      </div>
+
+      <div class="panel">
+        <h2>2. 设置座位分布</h2>
+        <div class="row">
+          <div style="flex:1">
+            <label>行数</label>
+            <input id="rowsInput" type="number" min="1" max="20" value="5" />
+          </div>
+          <div style="flex:1">
+            <label>列数</label>
+            <input id="colsInput" type="number" min="1" max="20" value="6" />
+          </div>
+          <div style="flex:1">
+            <label>讲台位置</label>
+            <input id="frontLabel" type="text" value="讲台在上方" />
+          </div>
+        </div>
+        <div class="row">
+          <div style="flex:1">
+            <label>座位大小</label>
+            <input id="seatSizeInput" type="range" min="40" max="140" step="4" value="72" />
+          </div>
+          <div class="badge">当前:<span id="seatSizeValue">72px</span></div>
+        </div>
+        <div class="row">
+          <button id="buildBtn" class="btn secondary">生成座位</button>
+          <button id="toggleAllBtn" class="btn ghost">全部可用</button>
+        </div>
+        <div class="row">
+          <div class="checkbox-group">
+            <input id="noMixedGender" type="checkbox" checked />
+            <label for="noMixedGender">禁止男女同桌(左右座位)</label>
+          </div>
+        </div>
+        <div class="row">
+          <div class="badge">可用座位:<span id="seatCount">0</span></div>
+          <div class="badge">待分配学生:<span id="seatStudentCount">0</span></div>
+        </div>
+        <div class="muted">点击座位可以启用/禁用;禁用座位不会参与分配。</div>
+        <div class="stage-wrap">
+          <div id="seatStage" class="seat-stage">
+            <div id="frontLabelView" class="stage-label">讲台在上方</div>
+            <div id="seatGrid" class="seat-grid"></div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <section class="panel" style="margin-top:18px;">
+      <h2>3. 随机分配</h2>
+      <div class="row">
+        <button id="assignBtn" class="btn">随机分配</button>
+        <button id="shuffleBtn" class="btn ghost">重新随机</button>
+        <button id="resetAssignBtn" class="btn ghost">清空分配</button>
+      </div>
+      <div class="row">
+        <button id="exportBtn" class="btn secondary">导出 PNG</button>
+        <button id="printBtn" class="btn ghost">打印</button>
+      </div>
+      <div class="muted" id="assignHint">需要先导入名单并设置座位</div>
+    </section>
+  </div>
+
+  <script>
+    const state = {
+      students: [], // 每个学生: {name: string, gender: '男'|'女'}
+      seats: [],    // 每个座位: {id: string, active: boolean, label: string, row: number, col: number}
+      assigned: new Map(), // seatId -> student
+      rows: 5,
+      cols: 6,
+      seatSize: 72,
+      noMixedGender: true, // 默认禁止男女同桌
+    };
+
+    const el = (id) => document.getElementById(id);
+    const fileInput = el("fileInput");
+    const hasHeader = el("hasHeader");
+    const noMixedGender = el("noMixedGender");
+    const nameCol = el("nameCol");
+    const genderCol = el("genderCol");
+    const studentList = el("studentList");
+    const studentCount = el("studentCount");
+    const seatStudentCount = el("seatStudentCount");
+    const maleCount = el("maleCount");
+    const femaleCount = el("femaleCount");
+    const seatGrid = el("seatGrid");
+    const seatStage = el("seatStage");
+    const seatCount = el("seatCount");
+    const assignHint = el("assignHint");
+    const seatSizeInput = el("seatSizeInput");
+    const seatSizeValue = el("seatSizeValue");
+    const frontLabelView = el("frontLabelView");
+
+    const setStudentList = () => {
+      studentCount.textContent = state.students.length;
+      seatStudentCount.textContent = state.students.length;
+      
+      // 统计男女数量
+      const male = state.students.filter(s => s.gender === '男').length;
+      const female = state.students.filter(s => s.gender === '女').length;
+      maleCount.textContent = male;
+      femaleCount.textContent = female;
+      
+      if (!state.students.length) {
+        studentList.textContent = "还没有导入学生";
+        return;
+      }
+      
+      studentList.innerHTML = state.students.map((student, idx) => `
+        <div>
+          <span>${idx + 1}. ${student.name}</span>
+          <span class="gender-badge ${student.gender === '男' ? 'male' : 'female'}">${student.gender}</span>
+        </div>
+      `).join("");
+    };
+
+    const buildSeats = () => {
+      state.seats = [];
+      state.assigned.clear();
+      seatGrid.innerHTML = "";
+      applySeatSizing();
+      
+      for (let r = 0; r < state.rows; r += 1) {
+        for (let c = 0; c < state.cols; c += 1) {
+          const seatId = `${r + 1}-${c + 1}`;
+          state.seats.push({ 
+            id: seatId, 
+            active: true, 
+            label: `第${r + 1}行${c + 1}列`,
+            row: r + 1,
+            col: c + 1
+          });
+        }
+      }
+      
+      renderSeats();
+      updateCounts();
+      assignHint.textContent = "点击座位设置可用状态,然后进行随机分配";
+    };
+
+    const renderSeats = () => {
+      seatGrid.innerHTML = "";
+      state.seats.forEach((seat) => {
+        const node = document.createElement("div");
+        node.className = "seat";
+        if (seat.active) node.classList.add("active");
+        
+        if (state.assigned.has(seat.id)) {
+          node.classList.add("assigned");
+          const student = state.assigned.get(seat.id);
+          if (student.gender === '男') {
+            node.classList.add("male");
+          } else {
+            node.classList.add("female");
+          }
+        }
+        
+        const label = state.assigned.has(seat.id) ? state.assigned.get(seat.id).name : seat.label;
+        node.innerHTML = `<span>${label}</span>`;
+        
+        node.addEventListener("click", () => {
+          if (state.assigned.size) return;
+          seat.active = !seat.active;
+          renderSeats();
+          updateCounts();
+        });
+        
+        seatGrid.appendChild(node);
+      });
+    };
+
+    const updateCounts = () => {
+      const activeCount = state.seats.filter((s) => s.active).length;
+      seatCount.textContent = activeCount;
+    };
+
+    const applySeatSizing = () => {
+      state.seatSize = Math.max(40, Number(seatSizeInput.value));
+      seatGrid.style.setProperty("--seat-size", `${state.seatSize}px`);
+      seatGrid.style.gridTemplateColumns = `repeat(${state.cols}, minmax(${state.seatSize}px, 1fr))`;
+      seatSizeValue.textContent = `${state.seatSize}px`;
+    };
+
+    const parseStudents = (rows) => {
+      const startIndex = hasHeader.checked ? 1 : 0;
+      const nameIndex = Math.max(0, parseInt(nameCol.value) || 0);
+      const genderIndex = Math.max(0, parseInt(genderCol.value) || 1);
+      const students = [];
+      
+      for (let i = startIndex; i < rows.length; i += 1) {
+        const row = rows[i];
+        if (!row || !row.length) continue;
+        
+        const name = String(row[nameIndex] ?? "").trim();
+        const genderRaw = String(row[genderIndex] ?? "").trim();
+        
+        if (name) {
+          // 标准化性别:支持"男"/"male"/"M"等
+          let gender = '男';
+          if (genderRaw === '女' || genderRaw.toLowerCase() === 'female' || genderRaw.toUpperCase() === 'F') {
+            gender = '女';
+          }
+          
+          students.push({ name, gender });
+        }
+      }
+      
+      state.students = students;
+      setStudentList();
+      assignHint.textContent = "已导入名单,请设置座位并分配";
+    };
+
+    const parseCSV = (text) => {
+      const rows = text
+        .split(/\r?\n/)
+        .map((line) => {
+          // 处理带引号的CSV
+          const result = [];
+          let inQuotes = false;
+          let current = "";
+          
+          for (let i = 0; i < line.length; i++) {
+            const char = line[i];
+            if (char === '"') {
+              inQuotes = !inQuotes;
+            } else if (char === ',' && !inQuotes) {
+              result.push(current.trim());
+              current = "";
+            } else {
+              current += char;
+            }
+          }
+          result.push(current.trim());
+          return result;
+        })
+        .filter((row) => row.some((v) => v));
+      parseStudents(rows);
+    };
+
+    const parseWorkbook = (data, isBinary) => {
+      const workbook = XLSX.read(data, { type: isBinary ? "binary" : "array" });
+      const sheetName = workbook.SheetNames[0];
+      const sheet = workbook.Sheets[sheetName];
+      const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 });
+      parseStudents(rows);
+    };
+
+    const readFile = () => {
+      const file = fileInput.files[0];
+      if (!file) {
+        alert("请先选择文件");
+        return;
+      }
+      const ext = file.name.split(".").pop().toLowerCase();
+      const reader = new FileReader();
+
+      reader.onload = (e) => {
+        if (ext === "csv") {
+          parseCSV(e.target.result);
+        } else {
+          const result = e.target.result;
+          parseWorkbook(result, ext === "xls");
+        }
+      };
+
+      if (ext === "csv") {
+        reader.readAsText(file, "utf-8");
+      } else if (ext === "xls") {
+        reader.readAsBinaryString(file);
+      } else {
+        reader.readAsArrayBuffer(file);
+      }
+    };
+
+    const shuffle = (arr) => {
+      const copy = [...arr];
+      for (let i = copy.length - 1; i > 0; i -= 1) {
+        const j = Math.floor(Math.random() * (i + 1));
+        [copy[i], copy[j]] = [copy[j], copy[i]];
+      }
+      return copy;
+    };
+
+    // 检查将某学生放入某座位时,左右邻座是否存在异性冲突
+    // 只检查已分配的邻座(右侧尚未分配时不检查)
+    const genderConflict = (seatId, gender, assignment) => {
+      const [row, col] = seatId.split('-').map(Number);
+      const leftId = `${row}-${col - 1}`;
+      const rightId = `${row}-${col + 1}`;
+      const left = assignment.get(leftId);
+      const right = assignment.get(rightId);
+      if (left && left.gender !== gender) return true;
+      if (right && right.gender !== gender) return true;
+      return false;
+    };
+
+    // 检查某座位的左侧是否是禁用座位或边界(即该座位是一列的起点)
+    const isRowStart = (seat) => {
+      if (seat.col === 1) return true;
+      const leftSeat = state.seats.find(s => s.row === seat.row && s.col === seat.col - 1);
+      return !leftSeat || !leftSeat.active;
+    };
+
+    const assignSeats = () => {
+      if (!state.students.length) {
+        alert("请先导入学生名单");
+        return;
+      }
+      
+      const activeSeats = state.seats.filter((s) => s.active);
+      if (!activeSeats.length) {
+        alert("请先设置可用座位");
+        return;
+      }
+      
+      if (state.students.length > activeSeats.length) {
+        alert("学生人数超过可用座位数量");
+        return;
+      }
+
+      if (!state.noMixedGender) {
+        // 不限制性别,直接随机分配
+        const seats = shuffle(activeSeats);
+        const students = shuffle(state.students);
+        const assignment = new Map();
+        students.forEach((s, i) => assignment.set(seats[i].id, s));
+        state.assigned = assignment;
+        renderSeats();
+        assignHint.textContent = "已完成随机分配";
+        return;
+      }
+
+      // 按行列顺序排列座位,确保逐列检查左右约束
+      const orderedSeats = [...activeSeats].sort((a, b) => a.row - b.row || a.col - b.col);
+
+      // 多次尝试,随机打乱学生后用回溯确保无男女同桌
+      const MAX_ATTEMPTS = 200;
+      for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
+        const students = shuffle(state.students);
+        const assignment = new Map();
+        const used = new Array(students.length).fill(false);
+
+        const backtrack = (seatIdx) => {
+          if (seatIdx === orderedSeats.length) return true;
+          const seat = orderedSeats[seatIdx];
+          // 如果学生已全部分配完,剩余座位跳过(座位多于学生时)
+          const assignedCount = assignment.size;
+          if (assignedCount >= students.length) return true;
+
+          // 随机遍历学生顺序
+          const order = shuffle([...Array(students.length).keys()].filter(i => !used[i]));
+          for (const i of order) {
+            const student = students[i];
+            if (!genderConflict(seat.id, student.gender, assignment)) {
+              assignment.set(seat.id, student);
+              used[i] = true;
+              if (backtrack(seatIdx + 1)) return true;
+              assignment.delete(seat.id);
+              used[i] = false;
+            }
+          }
+          // 如果没有合法学生可放(所有剩余学生都会产生冲突),则此路不通
+          return false;
+        };
+
+        if (backtrack(0)) {
+          state.assigned = assignment;
+          renderSeats();
+          assignHint.textContent = "已完成分配(严格禁止男女同桌)";
+          return;
+        }
+      }
+
+      // 理论上极端情况下无解(如男女比例导致必然相邻),回退到尽力模式
+      const seats = shuffle(activeSeats);
+      const students = shuffle(state.students);
+      const assignment = new Map();
+      students.forEach((s, i) => assignment.set(seats[i].id, s));
+      state.assigned = assignment;
+      renderSeats();
+      assignHint.textContent = "⚠️ 当前男女比例或座位布局无法完全避免同桌,已尽力分配";
+    };
+
+    const resetAssign = () => {
+      state.assigned.clear();
+      renderSeats();
+      assignHint.textContent = "已清空分配";
+    };
+
+    // 事件监听
+    el("loadBtn").addEventListener("click", readFile);
+    
+    el("clearBtn").addEventListener("click", () => {
+      state.students = [];
+      setStudentList();
+    });
+    
+    el("buildBtn").addEventListener("click", () => {
+      state.rows = Math.max(1, Number(el("rowsInput").value));
+      state.cols = Math.max(1, Number(el("colsInput").value));
+      buildSeats();
+    });
+    
+    el("frontLabel").addEventListener("input", (event) => {
+      frontLabelView.textContent = event.target.value.trim() || "讲台在上方";
+    });
+    
+    seatSizeInput.addEventListener("input", () => {
+      state.seatSize = Math.max(40, Number(seatSizeInput.value));
+      applySeatSizing();
+    });
+    
+    el("toggleAllBtn").addEventListener("click", () => {
+      state.seats.forEach((seat) => { seat.active = true; });
+      renderSeats();
+      updateCounts();
+    });
+    
+    noMixedGender.addEventListener("change", () => {
+      state.noMixedGender = noMixedGender.checked;
+    });
+    
+    el("assignBtn").addEventListener("click", assignSeats);
+    
+    el("shuffleBtn").addEventListener("click", () => {
+      if (!state.assigned.size) {
+        assignSeats();
+      } else {
+        assignSeats();
+      }
+    });
+    
+    el("resetAssignBtn").addEventListener("click", resetAssign);
+    
+    el("exportBtn").addEventListener("click", async () => {
+      if (!state.seats.length) {
+        alert("请先生成座位");
+        return;
+      }
+      const canvas = await html2canvas(seatStage, { backgroundColor: "#ffffff", scale: 2 });
+      const link = document.createElement("a");
+      link.download = "seat-plan.png";
+      link.href = canvas.toDataURL("image/png");
+      link.click();
+    });
+    
+    el("printBtn").addEventListener("click", async () => {
+      if (!state.seats.length) {
+        alert("请先生成座位");
+        return;
+      }
+      const canvas = await html2canvas(seatStage, { backgroundColor: "#ffffff", scale: 2 });
+      const dataUrl = canvas.toDataURL("image/png");
+      const win = window.open("", "_blank");
+      if (!win) return;
+      win.document.write(`<!doctype html><html><head><title>打印座位</title></head><body style="margin:0;display:flex;align-items:center;justify-content:center;background:#fff;"><img src="${dataUrl}" style="max-width:100%;height:auto;" /></body></html>`);
+      win.document.close();
+      win.focus();
+      win.print();
+    });
+
+    // 初始化
+    noMixedGender.checked = state.noMixedGender;
+    buildSeats();
+  </script>
+</body>
+</html>

+ 98 - 0
换座位/换座位.py

@@ -0,0 +1,98 @@
+import os 
+from openpyxl import load_workbook
+
+def replace_numbers_with_names(file_path, name_dict, filename):
+    """
+    将Excel中的数字替换为字典对应的人名
+    :param file_path: Excel文件路径
+    :param name_dict: 替换字典 {数字: 人名}
+    """
+    # 加载工作簿
+    wb = load_workbook(file_path)
+    
+    # 遍历所有工作表
+    for sheet_name in wb.sheetnames:
+        sheet = wb[sheet_name]
+        
+        # 遍历所有单元格
+        for row in sheet.iter_rows():
+            for cell in row:
+                # 只处理数字类型的单元格
+                if isinstance(cell.value, (int, float)):
+                    num = int(cell.value)  # 转换为整数
+                    if num in name_dict:
+                        cell.value = name_dict[num]
+    
+    # 保存修改
+    wb.save(filename)  # 保存为新文件
+    print(f"替换完成!文件已保存至: {filename}")
+
+# 生成词典
+def generate_gender_dict(boys, girls):
+    """
+    生成男生编号为奇数、女生编号为偶数的词典
+    参数:
+        boys: 男生名单列表
+        girls: 女生名单列表
+    返回:
+        result_dict: 生成的词典
+        max_boy_id: 男生最大编号
+        max_girl_id: 女生最大编号
+    """
+    result_dict = {}
+    # 男生分配奇数编号(从1开始)
+    for i, boy in enumerate(boys, start=1):
+        boy_id = 2*i - 1  # 生成奇数序列:1,3,5...
+        result_dict[boy_id] = boy
+    
+    # 女生分配偶数编号(从2开始)
+    for i, girl in enumerate(girls, start=1):
+        girl_id = 2*i  # 生成偶数序列:2,4,6...
+        result_dict[girl_id] = girl
+    
+    # 计算最大编号
+    max_boy_id = 2*len(boys) - 1 if boys else 0
+    max_girl_id = 2*len(girls) if girls else 0
+    
+    return result_dict, max_boy_id, max_girl_id
+    
+
+def transform_dict(original_dict, max_boy, max_girl):
+    """
+    对词典编号进行变换:编号加20后模对应的最大编号
+    参数:
+        original_dict: 原词典(男生奇数编号,女生偶数编号)
+        max_boy: 男生最大编号
+        max_girl: 女生最大编号
+    返回:
+        new_dict: 变换后的新词典
+    """
+    new_dict = {}
+    
+    for key, value in original_dict.items():
+        # 判断是男生还是女生
+        if key % 2 == 1:  # 奇数编号(男生)
+            # 加10后模男生最大编号+1
+            new_key = (key + 10) % (max_boy + 1)
+        else:  # 偶数编号(女生)
+            # 加10后模女生最大编号(处理0值情况)
+            new_key = (key + 10) % max_girl
+            if new_key == 0:
+                new_key = max_girl  # 0值替换为最大编号
+        
+        new_dict[new_key] = value
+    
+    return new_dict
+
+
+
+boys = ["何奇锴", "刘庆明", "杨棋竣", "张剑锋", "蔡白俊", "俞勇任", "林福任", "陆乙菘", "李诚嘉", "曾熠", "郑传承", "杨锦程", "陶永辉", "李致成", "钱潇", "朱槟", "李世涛", "赵德涵", "张家旗", "杨宸睿", "高一峻", "李滴", "肖力铭", "马梓寒", "普子烨", "杨建枢", "张奕轩", "梁金豪", "吴耀鸿", "罗朝胤", "鲁子平", "詹健", "陈浩", "孙李锦钊", "管晨寓", "高瑞璠", "王启颂", "梁颂源", "高翔", "石泰锦钖", "姚明梁", "周财豪", "章何铖", "罗浩铭", "陈维海", "吴寒现", "徐正阳", "罗子程"]
+
+girls = ["陈瑾璇", "潘志婷", "罗梦楚", "刘思羽", "叶锡", "陈修玉", "施微微", "谭闰之", "杨思彤", "卢玥熹", "李奕莹", "李彬慈", "陈贤睿", "李宝妹", "陈记娴", "洪爽笑", "吴媛媛", "李云杰", "阳静", "车嘉瑜", "罗尔君", "李梓熙", "姜奕彤", "吕思娴", "普梦瑾", "王思懿", "龙思淇", "何青卓", "杨杭榕"]
+dict0, max_boy, max_girl = generate_gender_dict(boys, girls)
+a = int(input("请输入需要换座位的次数"))
+dicta = dict0
+	
+for i in range(a):
+    dicta = transform_dict(dicta, max_boy, max_girl)
+    replace_numbers_with_names("Temp.xlsx", dicta, "37班座位表{}.xlsx".format(i))

BIN
综合素质表脚本.7z


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.