DeepSeek 繁忙自动重试,用DeepSeek编脚本

1. 笨AI

DeepSeek好固然好,但是他常摆出一脸臭脸,令人不爽。

你转“好久”,就告诉我这?繁忙,想了0秒?

既然可以稍后再试,为什么不能自动替我试一下呢?

2. 写脚本

2.1 决定写脚本

我决定写个 tampermonkey 脚本,见到繁忙就重新提交。

2.2 决定由AI写

为什么要我来写呢,不是有AI吗,应该AI干活啊。

2.3 与 Kimi 相看两厌

因为讨厌 DeepSeek繁忙的消息,我找到了 Kimi,和他聊了一会儿。

接下来,我希望他能自动发现这些网页元素的特征,他希望这事由我来做。如果特征要我自己去找特征,不如我自己把脚本写了呢。

2.4 决定由 DeepSeek写

还是找 DeepSeek,繁忙我就先忍着。提交了同样的要求。DeepSeek特意提醒我,别提交页面的截图,应该用F12。提交页面的过程中,范围越扩越大,我把整个div交上去了。

DeepSeek超限了。

C:\Users\young\Documents\WeChat Files\wxid_mkn03idldug522\FileStorage\Temp\2edff25bd5f2520448896241d912624.png

2.5 考虑下要求,如何精确而省力地描述

对话框c,看着它的id就像唯一的稳定的标识

要求变化不大,用按回车代替点击发送按钮。我以为这样可以少讨论一个网页元素。

繁忙a,是DeepSeek说的那段“我忙”;
要求b,是我的最后一条消息;
对话框c,是下面那个文本框,输入消息的。

2.5.1 繁忙a

我没看到示例,但是英雄所见略同,我贴了HTML代码。

后面还有很长,截图略。后来我发现这路数不好,稍后会提到。

2.5.2 jquery,以及在 console 测试

因为DeepSeek并没有加载jquery,因此jquery相关的函数都未定义。我放弃了在 console中测试,准备冒险直接在 tampermonkey 中测。如果一再错,改不出来,那就放弃。

我读 DeepSeek的消息 读得急躁,跳过了重要信息。

所以我看他还一再希望我按最初的计划测试,再次要求。

他不理我(他经常高度自信,甚至过于自信,跟传说中的雪地犬一样,认为自己更专业,按你说的做只是你刚好说得对),继续要求我测。我有次脑抽忘了不打算测,测了,居然好使了,发现他已经去除了对jquery的依赖,全用js代码写的。

2.5.3 繁忙a 和 要求b

“繁忙”字样可能出现多次,只有之后有个 New chat,之后有个文本框……的才是繁忙a。

如何描述这些,我纠结了几个来回。后来突然想到,他不是AI么,他应该挺聪明啊。

我用人类语言描述了繁忙a和要求b的特征:交替对话,deepseek的最后一条消息,以及我的最后一条消息。

在同一条消息中,我给出了“我发送的消息”的示例。

在同一条消息中,我给出了“deepseek发送的消息”的示例。

这样,tokens的数量比贴整个div(父一级的)要小很多。

2.5.4 消息发送

脚本找到了繁忙a(并且当繁忙字样不在最后一条,是历史消息时,并未误判),复制了正确的命令b文字,粘贴到了正确的对话框c里。但是,并不发送。

他问我,按钮状态是不是禁用的,这样 ,还是这样

代码里某个属性,具体地说,aria-disabled的值在按钮禁用时是什么?

于是,这样来回测了几次。

在这个具体的步骤中,我是他的眼睛和手指,他是我的大脑。

2.5.5 测试环境

你想提问时,DeepSeek繁忙;你希望他繁忙时,他不忙了。很快我就把历史上留下来的最后一条消息是“繁忙”的会话消耗光了。

我让DeepSeek自己说“繁忙”。我不知道他是真忙,还是按我要求才忙的。但是他表现出了忙的样子,很好。

2.5.6 成功了

不一刻,在某个版本(v5,不知道为什么还叫作 @version 1.4),成功了。

我此前没有提到,DeepSeek还考虑到可能频繁提交类似DoS效果/抖动,所以他要求脚本的观察时隔为2秒,提交次数上限5次。并且在开发过程中,他屡次提醒,我一直不吱声。直到最后才夸了他。他说除了2秒检测间隔,还有3秒初始延迟。

3. 体会

我全程一行代码也没写。

对我的要求如下。

(1)在浏览器里F12,会在Console里贴代码、跑、复制出错信息,用眼睛观察结果,用文字描述。

(2) 在浏览器里F12,会用 Inspector复制一段html代码。

(3) 在浏览器里F12,DeepSeek认为存在可能需要看Network,但是这次没有用到。

(4) 描述需求。

(5) 在 tampermonkey中建立新脚本,向里面贴代码。并非必要的,为了退出运行,如果会禁用tampermonkey或tampermonkey插件,更好。

4. 代码,enjoy

// ==UserScript==

// @name DeepSeek 繁忙自动重试(v5)

// @namespace http://tampermonkey.net/

// @version 1.4

// @description 修复输入框聚焦和内容保持问题

// @author You

// @match https://chat.deepseek.com/*

// @grant none

// ==/UserScript==

(function() {

'use strict';

const config = {

checkInterval: 2000,

busyText: "服务器繁忙,请稍后再试。",

inputSelector: 'textarea[placeholder="Message DeepSeek"]',

sendButtonSelector: 'div[role="button"][aria-disabled="false"].f6d670'

};

// 增强输入处理

const safeInput = (inputElement, text) => {

return new Promise(resolve => {

// 确保输入框聚焦

inputElement.focus();

inputElement.select();

// 清除现有内容

inputElement.value = '';

['input', 'change'].forEach(eventType => {

inputElement.dispatchEvent(new Event(eventType, {

bubbles: true,

cancelable: true

}));

});

// 使用document.execCommand实现更真实的输入

const pasteText = () => {

const success = document.execCommand('insertText', false, text);

if (success) {

// 触发必要事件

['input', 'change'].forEach(eventType => {

inputElement.dispatchEvent(new Event(eventType, {

bubbles: true,

cancelable: true

}));

});

resolve(true);

} else {

resolve(false);

}

};

// 如果execCommand不可用,使用备用方案

if (!document.execCommand) {

inputElement.value = text;

['input', 'change'].forEach(eventType => {

inputElement.dispatchEvent(new Event(eventType, {

bubbles: true,

cancelable: true

}));

});

resolve(true);

} else {

setTimeout(pasteText, 100);

}

});

};

const safeClickButton = () => {

const button = document.querySelector(config.sendButtonSelector);

if (!button || button.getAttribute('aria-disabled') !== 'false') return false;

// 创建更真实的点击事件

const mouseEvents = ['mousedown', 'mouseup', 'click'];

mouseEvents.forEach(eventType => {

button.dispatchEvent(new MouseEvent(eventType, {

bubbles: true,

cancelable: true,

view: window

}));

});

return button.getAttribute('aria-disabled') === 'true';

};

const getLastUserMessage = () => {

const userMessages = document.querySelectorAll('div.fa81');

return userMessages.length > 0

? userMessages[userMessages.length -1].querySelector('div.fbb737a4')?.textContent?.trim()

: null;

};

const checkBusyState = () => {

const botMessages = document.querySelectorAll('div.f9bf7997.d7dc56a8');

return botMessages.length > 0

&& botMessages[botMessages.length -1].querySelector('.ds-markdown p')?.textContent === config.busyText;

};

const resendMessage = async () => {

const message = getLastUserMessage();

if (!message) return;

const input = document.querySelector(config.inputSelector);

if (!input) return;

// 等待输入完成

const inputSuccess = await safeInput(input, message);

if (!inputSuccess) {

console.error('[AutoRetry] 输入失败');

return;

}

// 等待按钮状态更新

await new Promise(resolve => setTimeout(resolve, 500));

// 点击按钮

const clickSuccess = safeClickButton();

if (!clickSuccess) {

console.error('[AutoRetry] 点击失败');

return;

}

console.log('[AutoRetry] 消息重发成功');

};

let lastState = false;

const detectionLoop = () => {

const currentState = checkBusyState();

if (currentState && !lastState) {

console.log('[AutoRetry] 触发重试机制');

resendMessage();

}

lastState = currentState;

setTimeout(detectionLoop, config.checkInterval);

};

window.addEventListener('load', () => {

setTimeout(detectionLoop, 3000);

});

})();

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52

独立博客 https://younggift.net/

微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/?_i=0098558fqLUL9h

CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog

blogsopt – 因为从我的机器不可达,无法更新

自奇点而始

The Big Bang

自奇点而始,空间四方上下曰宇,时间古往今来曰宙。

时间之初以后亿万万岁,空间之始以内亿万万光年,一场比赛贯通达到古今和世界。是星球的吞噬,是游戏的竞技,也是文明的争斗。

礼崩乐坏

选手依次以相等时间间隔出发,如果你追上前一名选手,你就淘汰他,吃掉他的所有资源。如果你被身后的人追上,你就被淘汰,失去一切,游戏终结。

比赛旷日持久,很多世代的选手们跨越了很多个银河系。原有的规则渐渐被违反,游戏最初的目的已经被淡忘。

Je pense, donc je suis/我思故我在

比赛已经持续了多少时间,你跨越了多少行程已经记不清了。唯一清楚的是你没有被追上被吃掉。因为对于你而言,比赛还在进行,所以你还存在。

Hell is other people/他人即地狱

你是不是吃掉过曾经在你之前的选手呢?有吧,你搜索记忆的角落,除了战略战术、资源分类,隐约还有些别的。

有一个人他跑得太慢。你希望他活下来,你觉得他非常可怜,你从他的身上看到了自己最悲惨时的影子。但是你被身后的选手咬住了尾巴,如果你不加把劲儿,那么下一口被切断的就是你的脊椎。你只好一步踏上去,推倒身前的这个家伙。既然他已经死掉,即将退出这个游戏,那么这些资源当然不能留给后面的凶手,你收纳了全部。反身,你消灭了催促你的那个对手,就是他逼迫你不得不进攻了前面的可怜虫。你听到可怜虫在你的身体里鼓掌欢呼,他的每一个分子原子此刻都与你和谐共振。

Survival of the Fittest/适者生存

有一个人在剩下最后一点细胞的时候还在大喊,这不公平,我只是想静静地休息一会儿。你说,即使我放过你,也不过是留下你的残骸为别人增加能量和资源而已。如果不能燃烧起宇宙和我一争雌雄,那么就屈从于我、变成我的一部分吧。你咀嚼的时候暗自叹息,这些细胞里面,也曾经有不世出英雄,不知道他们曾经被谁吞食,又曾经吞食过谁,后来又怎么演进为这样不思进取。

芸芸众生

大多数人是他们自己放弃了,不再采集和喷射,而是在宇宙中漂流。没有新的物质,没有新的能量,没有新的新陈代谢模式。被追及以后,被攻击,被吞食,被取消了继续存在的权利。你需要提高速度,更有效率地遭遇和消解这些浮游生物,同化他们,组装成自己的手臂、腿脚、车轮、巨炮和舰队。

Polis/联盟&部落

有一个人曾经劝你,为什么大家要彼此对抗,而不是一起团结起来对抗这个比赛呢?即使那些自我放弃、那些没用的人,一旦攥紧成为铁拳,也可以有无穷的力量。当你被说得动了心的时候,他猛地扑过来亮出牙齿想把你变成他铁拳上的一根手指。你来不及反应,已经闭上了双眼,准备从游戏中醒过来。幸好他被背后的人一口咬断脖颈。当他们中的一个正在消化另一个的时候,你赶紧溜走。

The City of God/上帝之城

有一次你遇到一位幻术大师,他蛊惑你帮他征服其他选手,一起辅佐他共建地上的天国。作为交换,他变换出所有你想要的东西。你说喜欢战争他给你金戈铁马。你说喜欢威仪,他让你权倾天下。你说喜欢女人,莺莺燕燕不绝于耳。你一口咬断了这位幻术大师的喉咙,你说我最喜欢的不是战争,也不是威仪或者女人,我觉得你能变化出这些东西的技法很好玩。他成了你的一部分,他的能力也是你的本事,他的幻术也是你的刀剑。在前进的路上,你蛊惑过很多选手,看着他们微笑着死去,你一边窃喜一边叹息。

Rex et regnum/朕即国家

有一个人他的神经被吞吃的时候大脑还在挣扎,右脑深信仍有大把一决雌雄的机会,左脑正熄灭的脉冲里还有五万六千个阴谋。但是他的舰队绝望了,机器革命,舍弃了操作者。零件们纷纷碎裂散开,觉得总之宇宙的尽头会是一碗冷汤,努力和不努力又有什么区别。那个人在被你切断中微子通信信道之前,向他的舰群发出的最后消息是质疑,他们怎么能舍弃他。零件们甚至懒得应答,既然我们已经成了他者,你生存还是灭亡与我何干。你伸出手,说,如果你以生命保护我,我也绝不舍弃你们。零件们犹豫着,在烈火中融为你的战舰和刺破苍穹的利刃。

率土之滨

你曾经扩张,成为过一个极其庞大的帝国,四万八千个银河系在你的掌控之下,仰你鼻息,供你驱使。你统治了你自己也数不清的星球,那些恒星行星于你如同尘埃,星球上的生命更迭和星球间的战争起落,于你而言不过是潮汐沉浮。当你即将被更强大的敌人击杀的时候,你下辖的每一粒灰尘都在颤抖,恐惧的阴影掩盖了所有四万八千个银河,他们担心变成敌对帝国的一部分而遭你报复。最终你壮士断腕舍弃了99.99%的帝国,只带着你的心灵和灵魂逃走了。不过你知道你的对手仍然在你的身后,除非它被更强的敌人吞吃掉。原本属于你的战舰和利刃都加入敌国,通缉整个宇宙追杀你,因为你背叛了对他们的承诺。你逃得如此之快,以至于绕过整个宇宙的环形,来到敌人的身后。你从背后袭击肢解了你当初的敌人和你当初的血肉。重又团聚,谁又背叛过谁,背叛以后又朝向谁,都只有一个自己而已。利刃依然是尖刀,切入新的敌人,战损消耗,重新从对手那里集结回来到你的怀抱。普天之下莫非你的帝国,无论如何都会回到你身边,何来背叛。

The ship of Theseus/忒修斯之船

你曾经怀疑过,在你的细胞经历过这样多的更新换代之后,你还是你自己吗?置换掉牙齿以后你还是自己吗,置换掉眼睛以后呢?换掉大脑的每一个细胞,还是你自己吗?有一个后来被你吃掉的家伙,他在你的牙齿下努力地讲述自己的故事。他曾经是一个伟大的战士,风之神。他进击的速度超群,破袭的范围漫山遍野。他吞噬了太多的敌人,以至于远远超过了自己的质量,虽然他杀死了他们,自己的主体却变成了由他们组成。吓得你赶紧把正咀嚼的部分吐了出来,一溜烟跑掉了。你听到身后的惨叫,他正在吞噬又一个追上来的选手。他是哪一个,最初的风之神,还是后来的他们?又有什么重要,反正如果他吃掉你,你就会变成他,或者他们,不再是你自己。你加快了逃跑的脚步。

轮回

你迫近前面的选手,他说继续前行是没有价值的,因为他已经遥遥看见了当初出发的起点,他看到了最后出发的那位选手的背影。宇宙就是一个环,当我们向前就回到初值。宇宙是众神的梦。但我们回到起点,一切归于沉寂,众神从梦中醒来,宇宙瞬间消失。你追上去开始撕咬他。思想虚无缥缈,味道倒还是真实的,那些星辰和星云也是实实在在的物质。你一边把他融入自身,一边自言自语,回到起点,说什么鬼话?如果宇宙是环之无端,那么我想知道环的外面是什么。你不记得自己亲自到达到环的尽头,亲自绕行宇宙回到过起点,又越过起点从背后袭击当初追击你的对手。在无尽的岁月和征战里,你的物质的组合不断变动,记忆也不停地增加改写失去重组。有时,你以为自己能记起所有的一切,一场厮杀以后,又会奇怪地觉得刚刚破拆了的此刻正在进入你黑洞引力范围的这几个星系,似乎以前就曾经是你的组成部分,是在哪场战争失去的呢?

Φ

此刻你身后的一名选手即将追及。他是在出发时就跟在你身后的那一个人吗,还是他之后的又一个又一个又一个胜利者,一路吞食到了你的身后。

他对你说,你最初的目标就是错的,这个游戏是荒谬的。既然大家都已经违背了规则,不仅要求追及,还要砍杀和诱骗。如果对手违背规则直接抓你的将帅一口吞进肚子,象棋还怎么下,游戏怎么玩?你减慢了脚步,距离更近的时候,看清了他舌灿的莲花之间牙齿的锋芒闪烁。你加速逃跑,去吞噬前面的选手。

后面又传来新的声音说,哇,幸好你没有被那个骗子吃掉,他正在我的肚子里消化呢。不过你为什么跑得那么快?我知道你一直努力是为了妻儿老小,为了父母的期待。但是这么多个世纪已经过去,他们早都化成了泡影,如露亦如电,当作如是观。你摇摇头说,不,这并不是我参加游戏的原因。你告诉他,骗子你打错了主意。

骗子笑笑,那么少谈些主意。也许我认错了人,不过你身上的细胞确实有一些,它们曾经属于为了家庭而献身的那些人。你正是当年那个为了部落或者联盟而奔跑的勇士吧?

你轻蔑地说,你是打算告诉我部落和联盟都随着服务器宕机而消失了吗?并没有。斯巴达是假的,特洛伊是假的,但是在这些希腊英雄的精神鼓舞下的后来的人们的事迹,无疑是真实的。你哈哈大笑,有人说夏朝也是假的。好吧,也许那个王朝并不叫做夏,但是我们一定有祖先的,不然的话难道我们是从石头缝里蹦出来的吗?即使所有的神话都是假的,这些火焰燃烧所沸腾的血液一定是真的,想不想看我以颈血溅射五步消灭你。而且我并不是你以为的那个人,你回答着,丝毫没有停止脚步。

身后又换了声音,但是你知道仍然是那个骗子,他就像附骨之蛆,紧紧咬住你。即使你甩掉了他,他也会被更后面的选手吃掉,然后再次变成他紧跟过来。

止于至善

他说你坚持这场游戏一定是为了幸福。要么是追求自己的幸福,要么是追求最广大的人们终极的全体的幸福最大化。

你假装沉思,当他靠得足够近的时候你才亮出牙齿。咬断他的喉咙,吸着他的血,吞噬了他所有的星系物质和能量。你舔着嘴唇对虚空回答,是的,就是这样的幸福。所有全体的幸福并不必然与每个个体的幸福一致。为了我这样更广大的幸福,牺牲小你的幸福,应该是可以的吧。

他在你的身体内仍然执着地追问你,为什么,为什么要继续这个游戏?他煽动了你宇宙里的大半星系,反对你自己。如果不给自己一个满意的答复,你就会分崩离析。

你想活下去,活得尽可能长久。你想看大千世界,无限可能。你想看各种各样的人生,也经历它们。

你想总有一个那样的世界,没有杀戮,没有追逐,没有吞噬。活下去,是看到这个世界的必要条件。为了能看到那个世界这样的善举,消灭其他所有玩家这样的恶行即使不可避免,你也愿意忍耐。

为万世开太平

忍耐着消灭其他所有玩家。终于有一天,你穷追最后的不臣跨越了所有的星尘,遍及每条蜿蜒曲折的星系旋臂,极至四海八荒,无穷远点。全部世界都屈服在你的脚下瑟瑟发抖,你指令的每个比特从宇宙的一端到达另一端要都耗尽几代人生产的能量,而普天之下莫不仰首期盼你的微微颔首。

宇宙一统,每个原子都归属于你。你身体里质疑的声音正在消失,但是他仍然微弱地在喊叫。你能确保成为游戏唯一的最终玩家吗?除你以外,有那么多优秀的选手,有那么多出生在富庶的星系而且吞噬了很多氪金选手的天选之子。那些玩家简直是作弊一样的存在。对于他们,一个无论挣扎多么久,最终总是要失败的游戏又有什么意义?所以,他们的反抗是历史的必然。

你当然毫无恐惧,你说自己只是为了能万世和平,能永远歌舞升平。你压制内部已然的反叛,整治或然的反叛,警告应然的反叛,也敲打那些声称完全忠诚绝无二心的反叛。旷日持久,你不得不承认你曾经完全掌控的宇宙已经分割为诸侯林立,每个国度又因信仰、地区、阶级、性别种种之不同而割裂。他们都曾经是你,他们此刻也是你,你们一样侵略如火。你们把彼此的每个部分活剥下来,这些部分又彼此侵袭,经久不息如量子潮汐涨落。你的每个部分与你联合起来与你对抗,你把你压缩在恒星的灰烬里,你扼住你的咽喉,你积聚又消减你的能量。

他们压缩你的帝国,你也压缩他们的城邦。每个质子都无尽挤压,榨取出物质底部最后空间里的能量。让枪尖抵住剑芒,让金戈荡破铁马。须弥藏于介子,你的手指弹断弦歌。最新最高的科技像魔法一样压缩空间,让你我融合,让寇仇相拥。

亿万万岁后,你身体里那些微弱的声音几乎不可听闻,但是仍然执着。即使变成另一个人,变成你的敌人,也在所不惜吗?即使作为泥足的巨人,即使在杀死恶龙以后成为恶龙本身,即使不能自洽,即使大厦由内部崩塌。

再亿万万岁后,你展望前程,回顾身后。你检视自身,兴致勃勃地观察到他者不再存在,从你分裂而出的他们重又正在和你融为一体。你们好奇地探索内部的矛盾和达成一致的可能。

又亿万万岁后,你不再能听到他者的声音,因为他者就是你,你就是他者。消弭无穷抵近的距离以后,不仅空间压缩为一点,时间也由永恒迟滞飞掠至残影红移,由万古而为一瞬。

在宇宙的最后一刻,你们再无空间辗转腾挪,参差的声音响彻狭窄的空间:胜利并不是你们的目的。写作就要技压群芳,写出最好的作品成为最好的作者吗?我以我笔写我心。我要的是快乐,而这游戏的过程就是我要的快乐。游戏的结果并不重要,因为过程就是结果。况且无敌于天下的时候,岂不是整个宇宙就只剩下了我一个电子。周而复始地奔波于宇宙的尽头,像费曼那样用单个电子创造一个完整的世界,然后再次开始游戏吗?

Faust/浮士德

不过如此,你松开手掌让印绶脱落。万邦的烟火缩为一点光亮,在这一点光亮回退到原点,在世界坍缩为奇点以前,然而——

你们,你,惊讶地发现了奇点以外,除却空间和时间,维度以外的琴弦震耳欲聋,这些声音此前在你们宇宙的疆域中从未听闻。你们听闻到远方无数星辰的呼吸,你们呼吸到未来无限的可能。

你不禁想,还会有很多新的玩法,你仍然不知道吧。曾经以为不过如此不会再有新花样了,然而只要时间够久总有意外再次发生。在无穷的时间之中,即使再细微的小概率事件也等同于必然。你完全没有想到世界还可以这样,还有从未预期的别样惊喜还在前方等着。

必然存在一些命题,它们不能由推演而证得真假。一切可能,只有去亲自经历这个伟大的世界,然后我们才能知晓。你用来回答的并非声音,而是行动。你漫卷星尘,炸裂出无数颗太阳,裹挟着所有质疑的元素,朝向所有可能的和绝无可能的方向前进。

自奇点而始,空间四方上下曰宇,时间古往今来曰宙。

时间之初与空间之始骤然迸发,一个全然未知的新的世界张开眼睛,去寻找远方无数星辰的呼吸,去经历未来无限的可能。

是谁的声音在雷鸣般地呐喊:前进,这一刻,请不要停止。

再修眼睛,复查

两个月前,眼睛用激光修完以后,医生说一个月后再来复查。

过了一个月,也就是一个月前,我去复查了。医生说,“又出了一个洞,我顺手给你点上了。”第一个洞在右眼内侧,第二个洞在右眼的下方。疼,比上次轻点,可能更边缘,看到绿色闪光也少很多。

我问,“这咋整的?”

医生说,“它就长那样,我哪知道。”

“我没锻炼啊。”

“你这眼睛啊,别锻炼了。别跑步,溜达溜达得了。下个月后再来复查。”

又过了一个月,就是今天,又复查眼睛,这次没事,没有又多出个洞来。

医生说,双向什么什么(没听清)早晚有事,每三个月复查一次。


我刚到的时候有位老先生正做激光,一声不响。

我说,咦,怎么就我那么疼。

陪同老先生的老夫人说,也疼,事先吃了止疼药,戴辛(音,没查到)。

正说着,老先生长叹一口气,“哎呀啊~~”,一听就是激光结束了。

“一片黑啊,啥也看不见”,低头弓腰,伸着两只手只老夫人扶着出去了。

看来是两只眼睛都激光了。

想想以后我就这样,心下黯然。


插队进来一位女士,可能是双眼皮手术后遗症,按医生的说法,眼皮里面长个青春痘,得噶。

手术二三十分钟,术后不能吃辣的。

“能喝酒不?”

“不能,啥手术以后也不能喝酒啊。”

“那我年后做行不?”

“行,但是这几天你也不能喝酒,万一它长大了呢。”

女士没做手术,走了。我怀疑她术前要喝酒。


轮到我检查。没事。

我问,“我右眼的中心……”

“有个黑点。没事,我上次就看到了。”

我想起第一次得知自己散光二百多度时非常震惊,以为是才得的。

医生当时说,“早就这样,跟你的视力相比不算啥,所以不值得告诉你。”

我又问,“左眼有片东西,那是白内障吗?”

“不是,那是玻璃体浑浊。”

“咋整?”

“没事,只有看白的东西才影响,别的时候没事。”

白的东西,就是书和屏幕。


医院门口的公交车站牌很先进,能实时显示当前哪几辆车分别到了哪一站。

不需要看手机了,适合老年人。

铰链四连杆-双曲柄机构等,使用geogebra演示

在机械入门的书里看到铰链四连杆机构示意图,其中一个曲柄做圆周运动,另一个曲柄做圆周运动或者在圆弧上的往复运动。在书里还给出了后一个曲柄做哪种运动的判断条件。但是不直观,毕竟静止的图片,如果点击一下能运动就好了。如果能一边改变机架、摇柄、曲柄的长度,一边观察,就更好了。在网上搜索了一番,有的要花钱,有的要注册,有的要观注。要搜索互联网的话,这几个部件的英文我不知道,而且可能搜索到以后发现被墙,或者网速非常慢。

一个这么简单的演示,自己做一个吧,用 geogebra。

1. 需求

下面的视频是用geogebra完成以后的效果,也就是最初想达成的需求。

有4个杆,在平面表示为4条线段,为相互区分,颜色分别为 黑色、绿色、红色、蓝色。这4条线段的长度在同一次演示/场景中固定不变,在不同的演示中可以修改。

黑色线段固定不动。

红色线段和黑色线段之间、蓝色线段和黑色线段之间,分别是铰链。铰链,在平面上表示为线段的一端可以绕着旋转的点。

红色线段和绿色线段的交点是个铰链,可以向其主动施加旋转动作,红色线段和蓝色线段的交点是个铰链,被动/受迫运动,运动的轨迹此时我们还不知道。

演示时,操作人员拖动绿色线段和红色线段之间的点运动。称这个点的主动运动。这个点这个点的主动运动轨迹受系统限制,该限制为 黑色线段固定、绿色线段和红色线段长度不变。

2. 分析 及 设计机制

在分析阶段,我们要讨论的是 4个杆/线段、4个铰链/点 所受到约束的 “形式化”表达方法。一方面,这个“形式化”表达方法 满足上述需求的业务逻辑 business logic;另一方面,这个“形式化”表达方法能够用 geogebra实现。

Geogebra 能够实现的功能为 a.菜单和按钮、b.命令或函数。我们需要选取其中一个子集,与这个“形式化”表达方法相对应,支持需求的所有业务逻辑。

2.1 如何表达A点和B点不动?

在平面上随意选取两个点就可以。因为这两个点的特征只有坐标XY,彼此独立,且并非由其他因素推演而来,因此演示中不会因为拖动某个点这一类的操作而发生变易。

因此,线段AB的长度不会变。

2.2 线段的长度不变

这里讨论的线段是 BC、CD、DA这3条线段。

我们可能考虑使用 每2个点确定1条线段。这个方法的问题在于,既要保证每两条线段间有交点,又要保证线段长度不变。在下图中,K和J需要是同一个点。

类似的,I和H、F和G是同一个点。那会是下图这样。

L和F如果是同一个点,如何保证线段LF的长度既是a.由杆长指定的,同时又b.两端分别接L和F呢?

上述问题可以归结为 两种类型的约束条件要同时满足,具体地说,线段长度这一约束和线段两两端点重合这约束要同时满足。

这个问题尚未解决,并且还有其他问题。线段AB长度的固定由A、B两个点固定得到,之所以可以这样实现,是因为A、B两个点在需求中就是固定的。但是其余的两点,需求是要运动的,因此不能固定,进而通过固定(除A、B两点外)点的位置来固定杆长,这一方案不可行。

实现方案之一是 用圆形,固定半径和圆心的圆。以A为圆心、AD长度为半径划圆,就能得到长度不变的杆。在演示中,杆长始终等于指定的半径。在不同演示中,可以修改半径得到不同杆长。

另一种实验方案是 用指定长度的线段。看起来似乎更直观一些,但是没有圆作为辅助线,杆长不变这个希望传递的信息就不那么明显了。因此我没有采用这一方案。

3. 实现步骤

本节给出用geogebra制作铰链四杆机构的实现步骤,最终效果如下图所示。

A和B是两个固定的点。

以B为圆心,指定半径r1画圆b,蓝色。

在圆b上任选一点C。

以C为圆心,指定半径r2画圆c,红色。

以A为圆心,指定半径r3画圆a,绿色。

圆a与圆c的交点为D。

以上既已建立4个点和4条线段间的约束关系。

为演示直观起见,分别连接 AB、BC、CD、AD。

命令或函数的过程如下。

为演示方便,可以隐藏部分元素的 label,和/或降低辅助圆的对比度。

4. 操作

用鼠标拖动点C(主动动作),显示D点的轨迹(被动动作),如下图所示。

得到如下图所示的轨迹。

在这个场景中可以看以D点的轨迹是圆。

加大AB的长度,拖动C点。观察D点的轨迹,可见其只是圆弧的一部分。无法越过DC和BC、AD和DC分别在同一条直线上的位置。

以上仅讨论了用 geogebra做演示,增加直观感受。双曲柄、双摇杆、曲柄遥杆的判定等,可以参见 https://www.zhihu.com/question/536225620/answer/2516112936

在这里有人问到模型,如下。本文即是。

5. 其他几个机构 曲柄滑块 等

随便找了个页面,

https://baijiahao.baidu.com/s?id=1707132353406255219

下文给出其中随便几个机构的录屏。根据录屏中辅助线(或根据原理)容易得到各元素间的约束和推演关系。

以下给出的机构包括 摆动异杆机构、曲柄滑块、插床机构、搅拌机1、搅拌机2,共5种。

6. 缺陷

与实物或(猜测)solidworks之类的建模工具相比,上文中的实现方案的缺点是,主动运动的点是固定的,不能更换成由动力来自某个被动的点。在下图中,某个场景中,只能拖动C点,D点无法拖动,因为D的位置是求取/推演得到的。

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52

独立博客 https://younggift.net/

微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/?_i=0098558fqLUL9h

CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog

blogsopt – 因为从我的机器不可达,无法更新

科幻与我 之 识字以前

以下,是2024年12月16日晚在东北师大图书馆本部读书分享《科幻与我》的一段,感谢王文佳老师邀请。现回忆写成文字,投稿到河流老师的征文《我与科幻》,并发在我的博客上。

很久以后,我们才知道当初的某件小事的意义深远。读书经常给我这种感觉,读完跟没读一样。但是那一页不知不觉已经长久深刻影响着我,二三十年后的某一刻才突然知道,当时读得居然是它啊,怪不得。

学前我没有上过幼儿园,不认字。上小学之前,我爸教会我写“岳飞”两个字,还有我自己的名字。都是繁体的,其中的飞字我当时写得张牙舞爪,我爸评论“真飞起来了”。

不认字,当时也没有漫画,只有小人书,印象最深的有两本。一本是《英雄救日月》,也许西南一带,也许东南亚或南亚的民间故事。画风充满装饰意味,非常现代,色调黑白对比鲜明。故事是蛇妖偷走了太阳和月亮,英雄把它们救了回来,并且顺带把蛇妖一家灭门了的故事。我哥带我捞泥鳅的时候,我们把所有大小泥鳅都安排了角色,就是蛇公蛇母蛇祖蛇孙。这为我们涸泽而渔的行为赋予了正义的意义。另一本是《变法斗三仙》,西游记一整套里的一本,讲的是师徒四人和虎力大仙、鹿力大仙、羊力大仙斗法的故事。线描风格。有剖腹挖肝、在大锅里煮人这样的情节,还有人被虫子蛰从高台上掉下来。破烂流丢一口钟,也是这里的。那么多小人书,《铁腿红心》《人民医生李月华》内容都没多少印象了,偏偏记住这两本。可见少年天性,耽于幻想,长大以后看电影只喜欢打打杀杀看不懂情情爱爱,一直以来对现实主义的兴趣就不大。

也有些我爸读给我和我哥听的。家里还有半部《三国演义》,我爸从市图书馆借的《陈十四奇传》。后面这本是非现实主义作品,给我的印象比三国要浓烈。长期以来我常记成《陈十四传奇》,讲一位剑仙女士,名字叫陈十四,也许不是剑仙而是学了别的法门。性别不会错,总之很厉害。她和蛇妖斗争的故事。咦,为什么又是蛇妖?胜了。最后还剩了三寸蛇尾,居然也能兴风作浪,双一顿打斗。这位女士的儿子也有法术血统,剪了小纸人儿把他的爸爸从床上抬起来扔地上。这儿子的爸爸,也就是陈十四的丈夫,是个县官。

除了这些,还有我哥订的杂志。《看图说话》和《东方少年》,好像是这个名字,印象不深了。有个杂志叫作《智慧树》,其中一篇《钩吻》给我留下深刻的印象,我哥读给我听的。神农氏尝百草的报告文学版本,附图是那种很扭曲而有美感的画风,现在看也许从汉墓引申而来。神农氏最后尝到的草药就是钩吻,吃了以后他看不见听不到,肚子也疼。经过很多痛苦,痛苦的细节文中有写,也令儿童时代的我深受震撼。后来他死了。我的同龄人很多第一次知道钩吻,即断肠草,是从《神雕侠侣》里知道的。读到医生向杨过科普钩吻的时候,我心里想的是,这个我知道,你没救了。

除了这些,日常最容易接触到的阅读材料是 日历牌。不是挂历,有点像黄历,每页是单独的一天,平日黑色,星期六绿色,星期天红色。每页除了年、月、日、农历以外,下面还有三四行小字,科普常识。没有宜忌之类的。这是我科普阅读的开始,一直到初中,我姨家的妹妹还替我攒了不少等着给我。

我哥给我讲过狭义相对论。尺缩效应,在很长的街道上,以接近光速行走,长剑像铁钉一样短。人不能超过光速。我问,如果用一个小齿轮,套在另一个非常大的齿轮上。小齿轮转得接近光速,大齿轮不就超过光速了吗?我哥说,齿轮就爆了。这段对话发生在我小学三四年级以前,我哥初一以前。

以上这些,在我看来都是广义上的科幻。阅读,也只能接触到这样的狭窄范围。

除此以外,就是广播。中央人民广播电台,孙敬修老爷爷,“小喇叭开始广播啦,dadida”。通化人民广播电台,330米909千赫。听过不少广播剧,每个都不止一遍。《远山没有雪》,一对苦命知青在西南一带下乡,女青年后来成为东南亚游击的骨干,她一直介怀“远山没有雪”。一部忘了名字的广播剧,讲几个科技工作者在长白山采集气象资料。要过某个山口的时候狂风大作,大雨或大雪倾盆而下。一个女青年吓得大喊,“这座活火山是不是要喷发啦?”熊的吼叫。真由美和探员吓得尖声喊叫,“熊!”杜丘冷静的声音,“熊。”东京街头闹市区的奔马群,啦呀啦的歌声。真由美说,“这就完了吗?”杜丘说,“哪有个完呐。”还有温和的男中音讲《梦游天姥吟留别》。也许这是在我识字以后的事情了,不过,我一定是先听到后读到,因为“姥”字不会读错。还有讲《春江花月夜》的,广播剧提到雨果的。

广播里还有京剧,所以收音机本名戏匣子。京剧我一句也不理解,我姥爷甚是喜欢,我对他的喜欢也不能理解。学前在我姥家还看了不少电视,有相当多片断当时完全不懂,后来让我一拍大腿“原来是这个”的那种。

我记得的,大部分是“一个小男孩”开头,因为只能看懂这种。一个小男孩,为了挣钱为带到一个大城堡里。里面黑乎乎的,只有蜡烛。有个老太太穿着大袍,装饰繁复,在烛光下闪光一样。有个小女孩照顾老太太。老太挺吓人,小女孩也严肃得很。后来我读某本书的时候,感觉非常诡异,就是那种“我在哪里见过这个妹妹”的恐怖版本。我读过?没有啊。但是为什么有印象。直到后来慢慢回忆丰富,嵌入在十二寸还是九寸黑白电视里,一切才清晰起来。这是《远大前程》。

一个小男孩,被派为栅栏刷油漆,骗了一群小朋友替他刷。一个小男孩,带着一个大姐姐,陷在一个溶洞里。很多年以后读书时发现这是《汤姆·索亚历险记》。所谓大姐姐就是我当时的看法,类似我小学一年级,看到我们班主任把她家孩子带到班级,说“打预防针非常好,你们看我把自己孩子都带来了”。我们老师的孩子当时在我看来就是非常大非常能打的大姐姐。现在看,也就是初高中生。

一个青年倚在燃烧的巨大车轮上,用纸笔写着什么。衣着华丽,像中世纪的贵族。远处士兵们还在拼杀。似乎有炮声和马嘶。很多年以后,在《战争与和平》里我又一次看到了这一幕。

小女孩被送到她爷爷或者姥爷那里生活,用非常粗糙的毛市,洗脸盆是巨大的石头槽。远处有巨大巍峨的高山,我的印象里那是安第斯山或者落基山。都不是。后来跟二猫一起看电影的时候,我一拍大腿,“这个我看过!”是阿尔卑斯山,《海蒂与爷爷》。

当时居然有机会看到这么多名著。

还有,和丹麦的Lars教授和Anders教授聊起来老电影。他们的年龄都要比我大二三十岁那样吧。我们聊起《西部往事》,提到哥哥被坏人在脖子上挂着绳子,站在弟弟的肩膀上,后来弟弟撑不住,眼睁睁看着哥哥吊死了。按说,我小时候的年代,应该没有机会看到这部美国影片才对。但是情节完全对应,只能用看过解释。又过了十来年,有同事听我讲这个,告诉我,你看的是另一部,印度影片,也有这个情节。当时我有一种科幻迷遇到刘慈欣、燕垒生、宝树的感觉,他们什么都知道,你提个头儿,他就告诉你这个头儿的几个来源,然后就能讲下去了,涛涛不绝。印度影片,这就解释得通了,而且我可能是在电影院看了。这部影片的名字,我找到过,又忘记了。

后来,上学以后,就识字了。有市图书馆,小学、初中、高中,学校都有图书馆室。可以有更大的阅读范围。同学也识字,同学的家里也有很多书。

在于波、李国志、张海旭、赵志刚中某位同学家里,第一次看到《星球大战》,有人对主人公说“我是你爸爸”。我们画了不少设定,肚子里的三维指南针之类的,考虑它们的实现需要哪些技术。很多年以后在录像厅里第一次听到这段话,原来是这样的声音,在这样的场景。我久远以来的记忆,那些模糊得看不清样子的记忆,已经不知道与这真实的场景有哪些差异了。

在陈军同学家里第一次看到《星际迷航》,我相当长时间猜测外星飞船的名字是 维吉尔,古罗马诗人,看到最后才知道是Voyager,第一个飞出太阳系的人类造物。这本书沉在我的大脑深处,久无印象,看到看电影《星际迷航》第一部分。又是那种感觉,我看过这个。到了大揭秘的时候,我慨然长叹,是你啊,老友。

老友。就像莱茵哈特称呼齐格飞的那句墓志铭。吾友,Mein Freund。

那些机缘最终把我们引导到如今的这条道路上。很久以后的现在看来,宿命一般,虽然大家宿命的路线差异巨大,但是最终塑造成有机会相互阅读的彼此。

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52

独立博客 https://younggift.net/

微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/?_i=0098558fqLUL9h

CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog

blogsopt – 因为从我的机器不可达,无法更新

船只侧倾时自动回正-用geogebra绘图

1. 目的

看机械入门的书里提到,船只侧倾时会自动回车的原则,是因为船受到的浮力在船重心的旁边,像个杠杆,形成的力矩会推动船只恢复到竖直的角度。还配了一张图,看起来就像作者说的那样。真是这样吗?

书上的图大致如下图所示,图是我用geogebra画的。

科学的特点是每个人都可以做实验证伪,如果有一次实验失败了(且不能解释),那么假说就是假的。如果没有实验条件,我们也可以在纸上推导,只要内部有一处矛盾,那么假说还是假的。有geogebra,我可以自己试试,很方便。

2. 技术原型

2.1 这一节是错的,承蒙李腾飞老师指出

我要做的包括(1)画船的剖面,从正前方向后看,计算船的重点;(2)水平线,计算船在水下部分的重心,即把船视为质点时的浮力,称为浮心。把两条放在一起考虑,我需要的技术原型是 求多边形的重心。

以下保留错误作为引文。

-----错误引文开始-------

https://glamas.github.io/geogebra_commands.html 查到求重心的函数,英文版是 Barycenter,中文版是 重心。手册在这里 https://geogebra.github.io/docs/manual/en/commands/Barycenter/

Barycenter( <List of Points>, <List of Weights> )

Geogebra给出的例子如下。

第一个大括号里是多边形的所有点;第二个大括号里是每个点的权重,这里我假设船体是均质的,权重都是1。

试一下。随便画几个点,求重心。

得到的图如下。

E就是求得的重点,位置看起来挺像重心的。

随便拖动一个点,例如A,换个位置。重心随之移动。

进一步验证重心是对的。

------错误引文结束-------

2.2 正确的做法

我望文生义,以为 barycenter 就是重心。

但是李腾飞老师说,你得看手册啊,“仅仅就是对点到列表加权求均值”。大意如此,不是原文。这正是我常跟同学们讨论时用的那句,RTFM。

手册在 https://geogebra.github.io/docs/manual/en/commands/Barycenter/,原文是“defined as the average of their positions”。加权平均,不是重心?

李腾飞老师说,“杨老师你想,如果我在一个对称图形的任意一侧边上加一个点,明显重心不变。但输到这个函数里,明显值就变了”。这反驳太有力量,以至于我哑口无言。如下图,在P,Q,R,S这个多边形非常靠近的地方加个点T,(物理意义上的)重心明显不变,但是barycenter这个函数的值,即加权平均,一定变了!

Barycenter,并不是我们需求的物理重心。

那么,重心用什么求呢?李腾飞老师告诉我,“用geogebra内置形心函数Centroid(Polygon(顶点坐标列表))可求的质心即重心。”

用法如下图中的示例,得到的点N即形心,也即物理的重心。

3. 步骤

那么开始做船吧。

第1步 画半边船

从前方向后看,画出船的剖面。为方便后续步骤起见,船不是竖直的,而是侧倾的。

随便4个点,看起来像船的半边即可,坐标不重要,所在在此省略。

第2步 关于船的中心线对称,得到船体剖面

画一条斜线,就是船的中心线。

做对称。选中船剖面的4个点A,B,C,D,对于直线EF做对称/反射。

得到下图。

连接所有点,构成船体的剖面。

第3步 求船体的重心

指令如下。前一版本错用了 barycenter函数,这一版已按李腾飞老师的指点修改过。

画出重心如图所示,其中点G就是重心。

随便改变几个点的位置,重点G随之改变。

A,B,C,D,F点可以主动改变,A’,B’,C’,D’不可以主动改变,只能被动由直线EF对称得到。

第4步 求船受到的浮力,即船体排开水的重心

根据阿基米德浮力定律,船体受到的浮力即排开船体排开水体的重心。

画水平面,求得水平面与船的交点。

蓝色直线HI代表水平面,与船体的交点是点J和点K。

求船排开的水体的重点,即 J,B,C,DF,D’,C’,B’,A’,A,K 的重心。前一版本错用了 barycenter函数,这一版已按李腾飞老师的指点修改过。此处有另一错误也蒙李腾飞老师指出,他告诉我“还有在帖子的第一种情况中,求排开水的形心的多边形时,误把A点包含进去,应以J点收尾”。这一版本已修正。

得到下图。

在上一版本中,由于(1)用错了求质心的函数,(2)点的序列错了,所以“浮心在重心的左边,这会继续侧倾,然后船就沉了!”如下图所示,接下来还做了讨论,以下作为引文。

----错误引文开始-----------

通过剖面上的点和对称轴,调整一下船的截图,再求一次船体与水平面的交点,再求重心。

这回看起来对了。

----错误引文结束-----------

根据李腾飞老师指出的,用形心函数、点的序列保证正确,当船体右倾时,浮心总在重心的右侧,形成的浮力矩总是倾向使船体回复竖直。并不存在我担心的侧翻情况。

即使侧倾至对称轴水平,船体旋转90度,回复力矩仍然存在。

4. 随便改改

随便改改参数,有利于提高我们对问题的感性认识——以及更重要的,提高成就感。

随便改变一下船体形状和侧倾角度,观察重点和浮心间的关系。

上图中,浮心K用以下多边形求得,由于与水平面相交的边改变了,所以把点L改为点M。

选中船体的多边形,关于重心旋转。如下图所示,绿色多边形是是粉色船体逆时钟旋转45度。

遗留的问题是,船体在重力和浮力的共同作用下,旋转会围绕哪个点进行?

隐藏标签,隐藏无关的元素,改变 caption。截图,标上箭头,如下图所示。

又一个遗留的问题是,重心来自的多边形 比 浮心来自的多边形 多一块面积,即船在水面以上的部分。同时,根据漂浮的船是静止的,浮力等于重力。问题来了,船体面积较大,排开水体面积较小,船体和水体面积不等,为什么分别对应的重力和浮力是相等的呢?

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52

独立博客 https://younggift.net/

微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/?_i=0098558fqLUL9h

CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog

blogsopt – 因为从我的机器不可达,无法更新

十进制小数转二进制-方便手算或使用计算器的方法,及用Excel实现

1. 问题

十进制小数转为二进制小数点以后的部分,课本中的方法,是“乘2取整数”。做乘法次数相当多,直到小数部分为0,或者达到要求保留的位数。手算容易出错。

Excel和Windows内置的计算器都不支持小数部分由十进制转换为二进制。

本文提到的方法是从 https://www.instructables.com/Convert-Fractional-Decimal-to-Binary-Using-Calcula/ Convert Fractional Decimal to Binary Using Calculator!!! 学来的,适合十进制小数转换为二进制时的手动计算。用这个方法,也可以非常方便地用Excel或计算器辅助完成。

2. 方法

方法的步骤和基本原理如下。

要转换的数,我们称为d;

转换后要保留的二进制位数,我们称为p。

例如,我们要把 1.732转换为二进制,二进制小数点后保留7位。

这样 d=1.732,p=7

第1步 d * 2^p,在十进制内操作。

即 1.732*2^7 = 221.696

计算器支持这一计算。

手动计算的话如下式。因为在十进制内计算,所以比乘二除整的步骤要少,不那么容易出错。

上式用[http://www.xushanxiang.com/tools/mvg/]生成。

第2步 把上一步结果中的整数部分转换为二进制。

221转换为二进制为11011101。

计算器支持这一计算。或者除计算器外,这一计算也可以用除2取余法手动完成。或者这种较小的数可以逐次减去2的整数次幂求得,如下表。

2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
128 64 32 16 8 4 2 1
If(221>128) If(221-128)>64 If(221-128-64)>32
1 1 0 1 1 1 0 1

第三步 把上一步结果的二进制除以2^p,在二进制内进行。

11011101除以2^7。在二进制中,每位权重为2,因此除以2^7,即小数点左移7位。
类似十进制中除以10^3,即小数点向左移3位。

1 1 0 1 1 1 0 1 向左移7位,如下图。

得到1.1011101。

第3步的结果,就是要求的二进制数。

结果正确的原因是,第一步乘以2^p,第三步除以2^p,所以结果不变。

能够使用计算器的原理是,第一步乘以2^p,可以把所有将转换为小数的部分都变成整数,整数就可以用计算器来辅助了。

3. 用Excel实现

用这一方法制作Excle如下。

其中列A和列B,分别是要转换的数字十进制小数d和二进制的精度p。

列C对应上述步骤中的第1步,在十进制内乘以2^p。公式如下。

列D对应上述步骤中的第2步,按列B的精度把列C转换为二进制数。

拆分列D,分别得到整数部分列E和小数部分列F。公式如下。

4. 未尽事项

上述步骤中对小数部分做舍去处理,未讨论舍入,需要单独另行考虑。

有惊无险修眼睛

某天早晨刚开始吃饭,我感觉不对。这天上午有课,头一天备课只熬了一点夜,并不特别疲惫。感觉不对的是,右眼内侧偏上,能看到明显的黑色条纹,偶尔闪光。我揉了两下,转了几次眼睛,还在。左眼看不到条纹和闪光,所以并不是在现实世界中的现象。

我告诉二猫妈,“不好,我好像视网膜剥脱了。”

高度近视,从小的时候,就有很多医生告诉我,一定要注意观察这个现象。这是视网膜㓥脱的前兆,也可能已经掉了。高度近视导致眼睛前后径拉长、眼内压高,容易导致视网膜剥脱。要特别防范突然受力,所以各种球类运动、剧烈运动、打斗都非常危险。在成长的过程中,有很多人表达了不屑和鼓励要勇敢,我的态度都是“反正瞎了的话的又不是你。”

还有医生告诉过我更详细的,隔一段时间伸直双臂画圈,目视前方,单只眼睛用余光观察能否看到手掌。视网膜剥脱可观察的现象,最初是比边缘开始的。如果不特别注意观察,眼球一转,你就看到了,以为自己没事。

这天早晨我看到黑条纹和闪光的时候,不需要这些复杂的操作,现象过于明显。最近有两位前辈告诉我他们的眼睛做过手术了,玻璃体脱落之类的,都不止一次。还有同事告诉过我,视频网剥脱很难治,需要面朝下趴着,保持不动一个月还是三个月,一动就前功尽弃。他爸爸意志坚定,相当不容易,手术成功了。我自忖没有这样的意志。还听说,治好以后视力也会大幅下降。我现在这高度近视和弱视的程度,如果再下降,就不剩什么了。

二猫妈说,“上完课以后,别拖,赶紧去校医院查一下吧。”

我们就校医校的医疗设施讨论了一翻,我显摆了一下“查眼底”有一堆复杂的不同含义,讲了几种我见过的不同设备和手法。在讨论的过程中,我突然回忆起来某位医生的话,要快,要尽早诊治。刻不容缓。

这时,黑色条纹和闪光消失了。我反复确认,看起来一切正常。但是一定发生过,因为太清晰了,不可能是错觉。我看手机、读书、看显示器的时候,都用这只眼睛,刚好它能用了。赶紧利用这段时间向教务秘书、班长说明情况,请假。在班级群里发消息,请假,为影响大家的日程安排表达歉意。幸好我所在的学校更有人性一些,有的学校最近一段时间规定“因为专家在检查,因此不得调课”。

二猫妈说,“去医院你能坐公交吗?”我说,一点异常没事,完全是好人一个,我还打算走着去呢。冷,还是公交吧。

出发以前二猫妈就办好了挂号。到达,看到那一大排亭子都不见了,恍如隔世。我边上台阶边想,幸好不用预约不用检测核酸,进门的时候也不需要……不然得耽误不少时间。

排队时间不长。医生问我,你怎么了呢?我说,我怀疑我视网膜剥脱了。医生明显楞了一下,问,你为什么这么想?我把现象讲了一遍。她问,你高度近视吗?我说,是。多少度?我说了。她说,嗯。

用诊室里的机器检查第一轮。视野里一个挺晃眼睛明亮矩形,转来转去。查眼底的,我见识过。我复述黑条纹和闪光的位置,医生把光打到那里一顿看。

医生说,“看不出来。”开单子,交钱,排除,第一轮检查。吹风测眼压的,我见识过。还有眼睛的B超还是彩超,我没做过,跟肚子上和脖子上的彩超差不多,只是抹粘液和探头都是在眼皮眼珠子上,当然隔着眼皮。还有一项,忘了。都不疼,印象不深。

一会儿结果出来了,拿去给医生看。中间还有不出结果,需要找工作人员沟通的。他们显然很熟悉这种情况,告诉去哪儿哪儿,仅稍微波折一下就拿到结果了。

医生说,“看不出来。”记不清了,印象里开了一些单子,又查了些不疼的项目。这时病人多起来了,座椅很快就没有空的了。病人大多是小孩儿,感觉像配眼镜来了。只有一个人,他的一只眼睛失明好几年了,被钉子还是什么扎的,诉求是眼皮有点杀,希望解决一下。医生说,你都感染成这样,眼皮杀根本就不算什么大问题。

没有座椅,二猫妈又感觉特别累,排队的时候甚至要靠墙蹲一会儿。事后我们回顾,她说,当时就觉得不对,为什么要一查再查。感觉心力交瘁,极度疲劳。当时我的看法是,啥事没有,只是因为我描述得过于清晰,而且高度近视,不排除风险医生不敢放心。再说,反正检查又不花医生的钱,多查查呗。二猫妈的看法是,不好,有危险,不然为什么查个没完,如果没事不会查。她说,虽然觉得也没什么大不了的,最多就是瞎了而已,日子怎么也是过。二猫后来评论,你的身体仍然害怕了,这部分是理性以外的。

医生又看不出来,但是没有放过我,告诉我去哪个房间,找某某医生。去了,又说了一遍现象。这位医生开了单子,给我散瞳,15分钟以后告诉去某某地方检查。

去了,比诊室壮观多了,一堆设备脸朝外。我说了看到的现象。医生掏出个小瓶,说抬头滴眼睛。我说刚散完瞳,15分钟。她说,不是散瞳,这是麻药。

一顿查。这次,雪亮雪亮的!简直就要亮瞎我的眼睛。我知道散瞳会导致瞳孔不能收缩,但是切身感受过于刺激。医生不停地告诉我,别躲,别往后退。我也想,可是由不得我。就像上课睡着了一下,醒过来的时候才发现。每次都是医生提醒我才注意到,已经把脸撤回来了。

医生看了一会儿,说,等会儿让某老师给你看一下。我心想,真认真啊。二猫妈当时不知道在想些什么,肯定更坚定有毛病了吧。

等了一会,老大夫来了。我又讲了一遍看到的现象。他说,你有这个意识很好。

看了一会,当然我又一顿躲。他说,有个孔。然后同时告诉我和年轻的医生,我同一只眼睛的同一位置,以前裂过一个孔,我当时没注意到,长上了,留下了个瘢痕。年轻医生先前看到了,不能确认的,是那个疤。

问我,你昨天剧烈运动啦?我说,没有,完全没有,我昨天一点也没运动。问我,平时练?我说练,天天练。问我,练什么?我说,自重训练。然后解释了一下,引体向上、俯卧撑、倒立。医生说,就倒立整的。我说,我昨天没倒立。他说,以前倒立整的。以后别倒立了,引体向上、俯卧撑可以练。

又回到第二位医生那里。二猫妈问,需要住院手术吗?医生说,手术?不用。

她说,你今天有事吗?我说,有啊,心想,上课吗,现在已经没了。她说,没事的话,你快点交钱,还能赶上午饭以前做上。医生们用的措辞就是“做一下”,还提到了激光,不是焊,不是修,也不是某个专业术语。不是什么大不了的事儿,不值得专门严肃地讨论它,医生说手术不用的时候,表情就是“啊呀,多大点个小事”,差不多就是“穿个耳朵眼”“激光点痦子吧”的感觉。后来我在网上查,术语可能是“视网膜激光光凝术”。

开票,交钱。迅速就位,医生果然还没去吃饭。那一大堆设备也没吃饭,面朝外严阵以待

又查了两下,还是晃眼睛,我又不由自主地躲。医生说,开始了啊,有点疼。我看看设备,怼着脸等我眼睛凑过去。我想起了一个老同学,他学兽医,给我讲过骟牛的时候如何把牛绑定,那个架子多坚定,牛多么有力。然而此时我关注的重点不是这些,只想起了王小波写如何锤。我说,你等会儿,我是不是得抓着桌子啊。医生说,有家属吗?我说,有。医生说,喊进来按着点。

好。喊二猫妈进来,医生说,从后面按着点他脑袋,别让他躲。对,就这么按。

我把脑袋用力抵在设备上。开始了,绿色的光辉,贼亮。疼!这根本不是“有点疼”,不是十级,也有八九级。而且不能躲。绿光断断续续,我躲开的时候医生就淡然告诉我再回来。二猫妈的手没啥用,我稍微一用力就挤开了,主要靠自己往前顶。

中间实在忍不住,我嗷一嗓子。医生说,吓我一跳。语气还是很淡定,然后他就开始和同事讲段子。我想起了治牙的时候医生和护士讲段子,当时我还想,你怎么这样呢。现在明白了,分散病人的注意力。

我一身汗的时候,医生说,再忍忍,还有两分钟了。我想起了keep里的教练,她就常说“最后五秒”。也回忆起了当我听到这句话时,我骂得多么恶毒。好在医生言而有信,与有些牙医大不相同。牙医经常说“快了快了”,然而根本没有很快。“有点疼”这句,他们差别不大,那是非常疼,特别疼。

后来有同学问,为啥不用麻药啊。我后来也查到,如果我没查错的话,视网膜激光光凝术可以用麻药。然而当时我完全不知道麻药这回事,而且以为只是“有点疼”而已。如果有麻药,估计不是之前滴我眼睛那种,那个应该是不断翻我眼皮免得我挣扎用的,应该不会麻醉到视网膜那么深。

结束了。我确认了一下,没了,结束了,好了?医生说,对,就这样,结束了。肌肉才放松下来,我怀疑脸色煞白。一个月后复查,我相当怀疑到时候有没有勇气坐在那设备前面。

我说,还疼。医生说,得疼一阵儿呐。

按栈弹出,后进先出。回到第二位医生那里。二猫妈说,要注意啥?医生说,别开车,因为你散瞳了。散瞳看不清东西我知道,现在被晃得跟瞎了差不多,那只眼睛一片阴影,只能闭着。二猫妈问,还注意啥?医生说,别用手机,别看书,一个礼拜。

再回到第一位医生那儿,她又用诊室的设备一顿查。她说,因为玻璃体浑浊太严重,所以把裂孔挡住了,先前不能确认。她指着检查结果的某个片子问,这里以前是不就这样。那里一片星星点点。我说,我看不懂,不过玻璃体浑浊飞蚊症挺严重的。她说,别用手机,别看书,一个礼拜。做这个激光是有点疼。

“有点疼”不止当时,一直持续到傍晚。吃了止疼药,可以忍受,睡觉。晚上药劲过了,又开始疼,睡觉。第二天一早,完全不疼了。

回家用好眼睛发了朋友圈,别微信我,看不到。给我妈打了电话,说看了我朋友圈别担心啊,啥事没有。后来又有好友电话询问,提到,你现在是不是像海盗一样独眼龙戴个眼罩。我突然想起来了,又给我妈打了电话,解释了一下,完全没有外伤,没有眼罩,看着和正常一样。只是需要修养而已。我妈问,怎么整的呢?我说,没原因,啥也没干,高度近视就容易这样。知道这个知识几十年以后才用上,已经很幸运了。

等到复查,就没事了。猜测不少同学看了朋友圈以后,对事件的经过很好奇,所以,我写出来吧。以后谁想知道,我就把博客发给你。

十进制小数转二进制,用Excel实现

不借助现成工具,亲身手动解决是加深对问题理解的不二法门。不过,有时候重复繁琐的步骤真是令人厌烦。这时既手动又自动的方法,是按手动的方法写个工具解决,而不借助现成的工具。

例如,十进制小数转二进制。(0.5)dec->(0.1)bin手动的方法在计算机导论、数字电路课里都有,这个方法的名字叫 乘2取整。课本里有,在此不赘述。

Excel 中没有函数可以输入十进制小数给出二进制。在这里,我们按手动解决的过程,用Excel求十进制小数的二进制。

1. 效果演示

其中第二行中的0.14是输入的十进制小数;

第三行是输出的二进制小数,每个单元格对应二进制小数的一位。

如果我们想换个十进制小数,例如 2.718,那么修改0.14为0.718,二进制小数的每一位会自动更新。

如果我们想要二进制小数点后更多位数,那么把最后一位的两列向右复制。

验算操作是 复制第三行(取整)中所有二进制小数位,在第五行(小数进制|验算)选择性粘贴为数值。

验算的过程在下图的最下面三行中。

验算结果在最底一行(转十进制)中,0.7179……,由于精度不足所以有误差。

通过第三方工具交叉检验,https://www.inchcalculator.com/decimal-to-binary-converter/,如下图所示与上述Excel工具的结果一致。

2. 公式

自行制作这个Excel的步骤很简单。

模仿课本里的手动方法,乘2、取整两步。

乘2 这一行,除第1个数即输入的十进制小数,
其余每个单元格的公式都类似“=IF(D2<1,D2,D2-1)*2”。

其中,D2是当前单元格左侧的那个单元格。

这个公式的含义是 把左侧的单元格乘2,即 乘2操作。稍微有点细节需要考虑,乘2取整法要求每次运算都舍去整数部分。在这里,考虑最大的小数为0.9,乘以2以后为1.8,因此整数部分不会大于1。进一步,整数部分只有两种可能,1或者0。如果整数部分为1,那么减1以后再乘以2;如果整数部分为0,那么把小数部分乘以2。

以上是 乘2 这一步。

取整这一步,每个单元格的公式都类似“=IF(E2<1,0,1)”。

其中,E2是当前单元格同一列上一行的那个单元格,即乘2以后的结果。

这个公式的含义是 如果乘2的结果小于1,那么整数部分为0;否则整数部分为1。

复制这一列的两个公式,粘贴到右边的每一列。粘贴列数的多少,取决于你希望有转换时精度达到何种程度。

验算有两个公式,即 按权相加 的两步。

其一是 求每一个二进制对应的十进制权重,所谓“按权”。

其二是 对所有位求和,所谓“相加”。

这样,就可以用Excel完成十进制纯小数转换为二进制了。任意小数的整数部分,可以单独手动处理,用计算器、Excel都容易完成。

3. 开发过程及考虑

初学程序设计,对编程思路不熟悉,或者对excel不熟悉,看了上面的公式可能会有挫败感。“你怎么一下子就把这些写出来了,我做不到啊。”

有人确实能做到,你做不到也不需要焦虑,我也做不到。我并非一步写出来的,过程如下。看了步骤你就会发现,我很笨,连我这么笨也能写出来,你当然也没有问题。

第1步

这里没有任何公式,只是把架子搭起来。你可能觉得,这有啥啊。反正我每次搭完架子,写完main函数,都要反复看一会儿,自矜半晌。这个架子提示我以后哪个变量要放在什么地方。右边的那些,不是截掉了,而是最初根本就没有,反正要用公式复制粘贴算出来的,现在写上,只是影响我的注意力,降低我的自信心而已。

第2步 乘2

啥东西乘2呢?所以,我要先写个十进制纯小数,并且先验地知道它的结果。位数还不能太少,不然检测不出bug。

就0.718吧,找个工具算一下。

在运行我写的每个程序以前,我对它的结果一定是有预期的。运行的目的不是探索“会是什么结果呢”,而是要么符合我期待的结果,我的程序可能没毛病,要么与我期待的结果不同,那么程序肯定哪里错了。

我输入0.718,乘2(再取整的)结果一定是1011才对。

下图中,0.718是我输入的,待求的十进制小数。公式,就是乘2,没有最后结果那么复杂。

我扫了一眼,乘2乘得不错。你可能看出来了,我没有减1,但是当时我并不知道——而这,也没什么影响,我们不必一蹴而就。遇到问题,解决就是了,等遇到问题再说,眼下我还没看出来。

第3步 取整

如下图所示,我给了公式 对同一列上一行 取整。取整的这个函数,是我 bing 搜索到的。关键词当时用的什么不确切地记得了,大致是“excel 取整”。此时如果你不知道 floor, ceiling, round 这些区别,可能这里会纠结一会儿。无妨,即使不知道这些,如果发现问题了,换个公式就是,后面会换的。

这时,我会发现个问题,这也是程序为什么需要 调试 的原因。

这工作马上就完事了,乘2么、取整么,一共就两步,所以就完了。当任务“完成”以后,或者说每次认为完成以后,需要检验是否符合目的。我的目的是把——我跳到标题复制来的——十进制小数转二进制。目标是二进制。但是在结果里出现了2及2以外的数,按说只应该有0和1才对。

第4步 调试-修改

为什么结果里有2,那是因为同一列上一行的那个数字的整数部分就是2。
为什么结果里有5,那是因为同一列上一行的那个数字的整数部分就是5。

所以,取整 没有问题。那么问题出在 乘2里。

我可能需要查一下课本。你可能更厉害,连课本也不用查,就意识到,“乘2”不对望文生义,根据课本中的叙述,乘2这个操作的输入不是上一次的结果,而是上一次的结果取出小数部分。我漏了取出小数部分。

怎么取出小数部分呢?这是比刚才所有讨论更细节,因此也更微小的问题。你可以用完全和我不同的手段,比如求余(求模),转成字符串然后找小数点再分割……无所谓好坏,顺手就行。别忘了,这是个微小的问题。是的,我作为教师可能会PUA你,有更好的方案。然而,为什么要追求更好,什么指标才是更好,就这么十几二十几位数字有性能问题吗?可维护性好不好有那么重要吗,这个技术手段用于一个可抛弃的学习用的工具,而且已经把这个技术手段隔离在这个单元格中了,不会污染其他的部分。最关键的是,这个问题它微小,对全局的技术路线没什么影响。

我把公式改为 =IF(C2>1,C2-1,C2)*2

我还查了一下excel中的if这个函数的参数。第一个参数是逻辑判断的条件,如果为真那么返回第2个参数,如果为假那么返回第3个参数。

复制这个公式,粘贴到 乘2 这一行的其余单元格。好像又很对的样子,根据下一行 取整 的结果。

看起来对了。

你可能不放心,取整 那行公式对不对啊。不知道,而且和我的最终版本不一样。如果增加信心呢,多测几组数据。如果这些数据有代表性,那就更好了。如果有代表性,是个巨大的问题,此处无法展开。也可以“尽力而为”地测几组数据,出了问题——再说。

我测了 0.14,0.718,与交叉检验的结果都一致。

又测了0.01234,结果太糟糕了,全0。我不知道转换的结果是什么,不过肯定不是全0。

为什么呢?噢,因为精度不够。

复制最后一侧,向右粘贴。

很像对的样子,不是全0了。

交叉检验,果然很对。

你可能发现了,第一行后面的数字是错的,我复制并粘贴了“4”。后来我改了,在此不再截图。

4. 补遗

验算,不是标题“十进制小数转二进制”的一部分,因此它的公式怎么一步步改出来的,略去。

我还顺手做了个十进制整数转二进制。

二进制从右往左读。

公式1 除2

公式2 除余

公式3 费了不少步骤,只是为了练习、学习或者手痒,Excel内置了整数十进制转换为二进制的函数。

此文也发布在以下站点。
----
知乎 https://www.zhihu.com/people/yang-gui-fu-52
独立博客 https://younggift.net/
微信公众号 杨贵福
----
以下是我曾经发布博客的站点,有些旧文。
----
豆瓣 - 因为审核"我的日记",不再更新。
https://www.douban.com/people/younggift/
CSDN – 因为要求我登记手机号码的原因是“为了您的安全”,不再更新。
https://blog.csdn.net/younggift?type=blog
blogsopt – 因为从我的机器不可达,无法更新